From 57ee3a22d0d9a1c357c469103ae765736dfbf9d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Mon, 6 Apr 1998 17:20:28 -0700
Subject: [PATCH] more stuff and more mutex locks around the existing stuff

Rev: src/modules/system/configure.in:1.21
Rev: src/modules/system/passwords.c:1.8
Rev: src/modules/system/system.c:1.48
---
 src/modules/system/configure.in |   6 +-
 src/modules/system/passwords.c  | 259 +++++++++++++++++++++++++++++++-
 src/modules/system/system.c     |  44 +-----
 3 files changed, 263 insertions(+), 46 deletions(-)

diff --git a/src/modules/system/configure.in b/src/modules/system/configure.in
index f25c52f784..59532e0ab9 100644
--- a/src/modules/system/configure.in
+++ b/src/modules/system/configure.in
@@ -1,4 +1,4 @@
-# $Id: configure.in,v 1.20 1998/03/28 13:46:49 grubba Exp $
+# $Id: configure.in,v 1.21 1998/04/07 00:20:28 hubbe Exp $
 AC_INIT(system.c)
 AC_CONFIG_HEADER(system_machine.h)
 
@@ -18,7 +18,9 @@ AC_HAVE_FUNCS(syslog link symlink readlink chown \
         geteuid getpgrp getpgid getppid getuid getgid setuid setgid \
 	getpwnam getspnam getgrnam getpwuid getgrgid \
 	getgrent setgrent endgrent getpwent setpwent endpwent \
-	chroot fchroot uname gethostname gethostbyname)
+	chroot fchroot uname gethostname gethostbyname \
+        getgrnam_r getgrent_r getgrgid_r \
+        getpwnam_r getpwent_r getpwuid_r )
 
 
 AC_CHECK_LIB(nsl, gethostbyname)
diff --git a/src/modules/system/passwords.c b/src/modules/system/passwords.c
index 55ecf970b1..ca0071eb68 100644
--- a/src/modules/system/passwords.c
+++ b/src/modules/system/passwords.c
@@ -1,21 +1,25 @@
 /*
- * $Id: passwords.c,v 1.7 1998/03/26 14:31:02 grubba Exp $
+ * $Id: passwords.c,v 1.8 1998/04/07 00:20:28 hubbe Exp $
  *
  * Password handling for Pike.
  *
  * Henrik Grubbström 1997-01-28
+ * Fixed to be semi-thread-safe by Hubbe. 1998-04-06
+ * Notice: the *pw* and *gr* functions are NEVER really thread
+ *         safe. If some other function executes a *pw* function
+ *         without locking the password_protection_mutex, we are
+ *         pretty much screwed.
  */
 
 /*
  * Includes
  */
-
 #include "system_machine.h"
 #include "system.h"
 
 #include "global.h"
 
-RCSID("$Id: passwords.c,v 1.7 1998/03/26 14:31:02 grubba Exp $");
+RCSID("$Id: passwords.c,v 1.8 1998/04/07 00:20:28 hubbe Exp $");
 
 #include "module_support.h"
 #include "interpret.h"
@@ -23,6 +27,7 @@ RCSID("$Id: passwords.c,v 1.7 1998/03/26 14:31:02 grubba Exp $");
 #include "threads.h"
 #include "svalue.h"
 #include "builtin_functions.h"
+#include "constants.h"
 
 #ifdef HAVE_PASSWD_H
 # include <passwd.h>
@@ -40,13 +45,66 @@ RCSID("$Id: passwords.c,v 1.7 1998/03/26 14:31:02 grubba Exp $");
 #ifdef HAVE_SHADOW_H
 # include <shadow.h>
 #endif /* HAVE_SHADOW_H */
+
+/*
+ * Emulation
+ */
+
+DEFINE_MUTEX(password_protection_mutex);
+
+#ifdef HAVE_GETPWENT
+#ifndef HAVE_GETPWNAM
+struct passwd *getpwnam(char *name)
+{
+  struct passwd *pw;
+  setpwent();
+  while(pw=getpwent())
+    if(strcmp(pw->pw_name,name))
+      break;
+  endpwent();
+  return pw;
+}
+#define HAVE_GETPWNAM
+#endif
+
+#ifndef HAVE_GETPWUID
+struct passwd *getpwuid(int uid)
+{
+  struct passwd *pw;
+  setpwent();
+  while(pw=getpwent())
+    if(pw->pw_uid == uid)
+      break;
+  endpwent();
+  return 0;
+}
+#define HAVE_GETPWUID
+#endif
+#endif
+
+#ifdef HAVE_GETGRENT
+#ifndef HAVE_GETGRNAM
+struct group *getgrnam(char *name)
+{
+  struct group *gr;
+  setgrent();
+  while(pw=getgrent())
+    if(strcmp(gr->gr_name,name))
+      break;
+  endgrent();
+  return gr;
+}
+#define HAVE_GETGRNAM
+#endif
+#endif
+
  
 /*
  * Functions
  */
 
 #if defined(HAVE_GETPWNAM) || defined(HAVE_GETPWUID) || defined(HAVE_GETPWENT)
-static void push_pwent(struct passwd *ent)
+void push_pwent(struct passwd *ent)
 {
   if(!ent)
   {
@@ -60,7 +118,9 @@ static void push_pwent(struct passwd *ent)
   {
     struct spwd *foo;
     THREADS_ALLOW_UID();
+    mt_lock(&password_protection_mutex);
     foo = getspnam(ent->pw_name);
+    mt_unlock(&password_protection_mutex);
     THREADS_DISALLOW_UID();
     if(foo)
       push_text(foo->sp_pwdp);
@@ -79,7 +139,7 @@ static void push_pwent(struct passwd *ent)
 #endif
 
 #if defined(HAVE_GETGRNAM) || defined(HAVE_GETGRUID) || defined(HAVE_GETGRENT)
-static void push_grent(struct group *ent)
+void push_grent(struct group *ent)
 {
   if(!ent)
   {
@@ -107,10 +167,12 @@ void f_getgrgid(INT32 args)
   struct group *foo;
   get_all_args("getgrgid", args, "%d", &gid);
   THREADS_ALLOW_UID();
+  mt_lock(&password_protection_mutex);
   foo = getgrgid( gid );
   THREADS_DISALLOW_UID();
   pop_n_elems( args );
   push_grent( foo );
+  mt_unlock(&password_protection_mutex);
 }
 #endif /* HAVE_GETGRGID */
 
@@ -122,10 +184,12 @@ void f_getgrnam(INT32 args)
   struct group *foo;
   get_all_args("getgrnam", args, "%s", &str);
   THREADS_ALLOW_UID();
+  mt_lock(&password_protection_mutex);
   foo = getgrnam( str );
   THREADS_DISALLOW_UID();
   pop_n_elems( args );
   push_grent( foo );
+  mt_unlock(&password_protection_mutex);
 }
 #endif /* HAVE_GETGRNAM */
 
@@ -139,11 +203,13 @@ void f_getpwnam(INT32 args)
   get_all_args("getpwnam", args, "%s", &str);
 
   THREADS_ALLOW_UID();
+  mt_lock(&password_protection_mutex);
   foo = getpwnam(str);
   THREADS_DISALLOW_UID();
 
   pop_n_elems(args);
   push_pwent(foo);
+  mt_unlock(&password_protection_mutex);
 }
 #endif /* HAVE_GETPWNAM */
 
@@ -157,11 +223,13 @@ void f_getpwuid(INT32 args)
   get_all_args("getpwuid", args, "%i", &uid);
 
   THREADS_ALLOW_UID();
+  mt_lock(&password_protection_mutex);
   foo = getpwuid(uid);
   THREADS_DISALLOW_UID();
 
   pop_n_elems(args);
   push_pwent(foo);
+  mt_unlock(&password_protection_mutex);
 }
 #endif /* HAVE_GETPWUID */
 
@@ -170,7 +238,9 @@ void f_getpwuid(INT32 args)
 void f_setpwent(INT32 args)
 {
   THREADS_ALLOW();
+  mt_lock(&password_protection_mutex);
   setpwent();
+  mt_unlock(&password_protection_mutex);
   THREADS_DISALLOW();
   pop_n_elems(args);
   push_int(0);
@@ -182,7 +252,9 @@ void f_setpwent(INT32 args)
 void f_endpwent(INT32 args)
 {
   THREADS_ALLOW();
+  mt_lock(&password_protection_mutex);
   endpwent();
+  mt_unlock(&password_protection_mutex);
   THREADS_DISALLOW();
   pop_n_elems(args);
   push_int(0);
@@ -196,6 +268,7 @@ void f_getpwent(INT32 args)
   struct passwd *foo;
   pop_n_elems(args);
   THREADS_ALLOW_UID();
+  mt_lock(&password_protection_mutex);
   foo = getpwent();
   THREADS_DISALLOW_UID();
   if(!foo)
@@ -204,7 +277,33 @@ void f_getpwent(INT32 args)
     return;
   }
   push_pwent(foo);
+  mt_unlock(&password_protection_mutex);
 }
+
+
+void f_get_all_users(INT32 args)
+{
+  struct passwd *pw;
+  struct array *a;
+  pop_n_elems(args);
+  a=low_allocate_array(0,10);
+  mt_lock(&password_protection_mutex);
+  setpwent();
+  while(1)
+  {
+    THREADS_ALLOW();
+    pw=getpwent();
+    THREADS_DISALLOW();
+    if(!pw) break;
+    push_pwent(pw);
+    a=append_array(a,sp-1);
+    pop_stack();
+  }
+  endpwent();
+  mt_unlock(&password_protection_mutex);
+  push_array(a);
+}
+
 #endif /* HAVE_GETPWENT */
 
 #ifdef HAVE_SETGRENT
@@ -212,7 +311,9 @@ void f_getpwent(INT32 args)
 void f_setgrent(INT32 args)
 {
   THREADS_ALLOW();
+  mt_lock(&password_protection_mutex);
   setgrent();
+  mt_unlock(&password_protection_mutex);
   THREADS_DISALLOW();
   pop_n_elems(args);
   push_int(0);
@@ -224,7 +325,9 @@ void f_setgrent(INT32 args)
 void f_endgrent(INT32 args)
 {
   THREADS_ALLOW();
+  mt_lock(&password_protection_mutex);
   endgrent();
+  mt_unlock(&password_protection_mutex);
   THREADS_DISALLOW();
   pop_n_elems(args);
   push_int(0);
@@ -238,6 +341,7 @@ void f_getgrent(INT32 args)
   struct group *foo;
   pop_n_elems(args);
   THREADS_ALLOW_UID();
+  mt_lock(&password_protection_mutex);
   foo = getgrent();
   THREADS_DISALLOW_UID();
   if(!foo)
@@ -246,5 +350,150 @@ void f_getgrent(INT32 args)
     return;
   }
   push_grent(foo);
+  mt_unlock(&password_protection_mutex);
+}
+
+void f_get_all_groups(INT32 args)
+{
+  struct group *gr;
+  struct array *a;
+  pop_n_elems(args);
+  a=low_allocate_array(0,10);
+  mt_lock(&password_protection_mutex);
+  setgrent();
+  while(1)
+  {
+    THREADS_ALLOW();
+    gr=getgrent();
+    THREADS_DISALLOW();
+    if(!gr) break;
+    push_grent(gr);
+    a=append_array(a,sp-1);
+    pop_stack();
+  }
+  endgrent();
+  mt_unlock(&password_protection_mutex);
+  push_array(a);
 }
+
+#ifdef HAVE_GETPWNAM
+void f_get_groups_for_user(INT32 arg)
+{
+  struct group *gr;
+  struct passwd *pw;
+  struct array *a;
+  char *user;
+  ONERROR err;
+  int base_gid;
+
+  check_all_args("get_groups_for_user",arg,BIT_INT | BIT_STRING, 0);
+  pop_n_elems(arg-1);
+  a=low_allocate_array(0,10);
+  mt_lock(&password_protection_mutex);
+  if(sp[-1].type == T_INT)
+  {
+    int uid=sp[-1].u.integer;
+    THREADS_ALLOW();
+    pw=getpwuid(uid);
+    THREADS_DISALLOW();
+    sp[-1].u.string=make_shared_string(pw->pw_name);
+    sp[-1].type=T_STRING;
+    user=sp[-1].u.string->str;
+  }else{
+    user=sp[-1].u.string->str;
+    THREADS_ALLOW();
+    pw=getpwnam(user);
+    THREADS_DISALLOW();
+  }
+  if(!pw)
+  {
+    mt_unlock(&password_protection_mutex);
+    pop_stack();
+    push_int(0);
+    return;
+  }
+  push_int(base_gid=pw->pw_gid);
+  a=append_array(a,sp-1);
+  pop_stack();
+
+  setgrent();
+  while(1)
+  {
+    int e;
+    THREADS_ALLOW();
+
+    while(1)
+    {
+      gr=getgrent();
+      if(!gr) break;
+      if(gr->gr_gid == base_gid) continue;
+      for(e=0;gr->gr_mem[e];e++)
+	if(!strcmp(gr->gr_mem[e],user))
+	  break;
+      if(gr->gr_mem[e]) break;
+    }
+
+    THREADS_DISALLOW();
+    if(!gr) break;
+
+    push_int(gr->gr_gid);
+    a=append_array(a,sp-1);
+    pop_stack();
+  }
+  endgrent();
+  mt_unlock(&password_protection_mutex);
+  pop_stack();
+  push_array(a);
+}
+#endif /* HAVE_GETPWENT */
 #endif /* HAVE_GETGRENT */
+
+void init_passwd(void)
+{
+  /*
+   * From passwords.c
+   */
+#ifdef HAVE_GETPWNAM
+  add_efun("getpwnam", f_getpwnam, "function(string:array(int|string))", 
+	   OPT_SIDE_EFFECT |OPT_EXTERNAL_DEPEND);
+#endif
+#ifdef HAVE_GETPWUID
+  add_efun("getpwuid", f_getpwuid, "function(int:array(int|string))", OPT_SIDE_EFFECT |OPT_EXTERNAL_DEPEND);
+#endif
+#ifdef HAVE_GETGRNAM
+  add_efun("getgrnam", f_getgrnam, "function(string:array(int|string|array(string)))",
+	   OPT_SIDE_EFFECT |OPT_EXTERNAL_DEPEND);
+#endif
+#ifdef HAVE_GETGRGID
+  add_efun("getgrgid", f_getgrgid, "function(int:array(int|string|array(string)))", OPT_SIDE_EFFECT |OPT_EXTERNAL_DEPEND);
+#endif
+#ifdef HAVE_GETPWENT
+  add_efun("getpwent", f_getpwent, "function(void:array(int|string))",
+           OPT_SIDE_EFFECT |OPT_EXTERNAL_DEPEND);
+  add_efun("get_all_users", f_get_all_users, "function(void:array(array(int|string)))",
+           OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND);
+#endif
+#ifdef HAVE_ENDPWENT
+  add_efun("endpwent", f_endpwent, "function(void:int)", OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND);
+#endif
+#ifdef HAVE_SETPWENT
+  add_efun("setpwent", f_setpwent, "function(void:int)", OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND);
+#endif
+#ifdef HAVE_GETGRENT
+  add_efun("getgrent", f_getgrent, "function(void:array(int|string|array(string)))",
+           OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND);
+  add_efun("get_all_groups", f_get_all_groups, "function(void:array(array(int|string|array(string))))",
+           OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND);
+
+#ifdef HAVE_GETPWENT
+  add_efun("get_groups_for_user", f_get_groups_for_user, "function(int|string:array(int))",
+           OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND);
+#endif /* HAVE_GETPWENT */
+#endif
+#ifdef HAVE_ENDGRENT
+  add_efun("endgrent", f_endgrent, "function(void:int)", OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND);
+#endif
+#ifdef HAVE_SETGRENT
+  add_efun("setgrent", f_setgrent, "function(void:int)", OPT_SIDE_EFFECT |OPT_EXTERNAL_DEPEND);
+#endif
+}
diff --git a/src/modules/system/system.c b/src/modules/system/system.c
index 5551153f7e..174917f431 100644
--- a/src/modules/system/system.c
+++ b/src/modules/system/system.c
@@ -1,5 +1,5 @@
 /*
- * $Id: system.c,v 1.47 1998/03/26 14:31:03 grubba Exp $
+ * $Id: system.c,v 1.48 1998/04/07 00:20:28 hubbe Exp $
  *
  * System-call module for Pike
  *
@@ -14,7 +14,7 @@
 #include "system.h"
 
 #include "global.h"
-RCSID("$Id: system.c,v 1.47 1998/03/26 14:31:03 grubba Exp $");
+RCSID("$Id: system.c,v 1.48 1998/04/07 00:20:28 hubbe Exp $");
 #ifdef HAVE_WINSOCK_H
 #include <winsock.h>
 #endif
@@ -943,6 +943,8 @@ void f_RegGetValue(INT32 args)
 }
 #endif
 
+extern init_passwd(void);
+
 /*
  * Module linkage
  */
@@ -1040,43 +1042,7 @@ void pike_module_init(void)
   add_efun("closelog", f_closelog, "function(:void)", 0);
 #endif /* HAVE_SYSLOG */
 
-  /*
-   * From passwords.c
-   */
-#ifdef HAVE_GETPWNAM
-  add_efun("getpwnam", f_getpwnam, "function(string:array)", 
-	   OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_GETPWUID
-  add_efun("getpwuid", f_getpwuid, "function(int:array)", OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_GETGRNAM
-  add_efun("getgrnam", f_getgrnam, "function(string:array)",
-	   OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_GETGRGID
-  add_efun("getgrgid", f_getgrgid, "function(int:array)", OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_GETPWENT
-  add_efun("getpwent", f_getpwent, "function(void:int|array)",
-           OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_ENDPWENT
-  add_efun("endpwent", f_endpwent, "function(void:int)", OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_SETPWENT
-  add_efun("setpwent", f_setpwent, "function(void:int)", OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_GETGRENT
-  add_efun("getgrent", f_getgrent, "function(void:int|array)",
-           OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_ENDGRENT
-  add_efun("endgrent", f_endgrent, "function(void:int)", OPT_EXTERNAL_DEPEND);
-#endif
-#ifdef HAVE_SETGRENT
-  add_efun("setgrent", f_setgrent, "function(void:int)", OPT_EXTERNAL_DEPEND);
-#endif
+  init_passwd();
 
 #ifdef GETHOSTBYNAME_MUTEX_EXISTS
   add_to_callback(& fork_child_callback, cleanup_after_fork, 0, 0);
-- 
GitLab