From fa3f1f47cbee8d8cd572f6986583c8e95f85a562 Mon Sep 17 00:00:00 2001
From: Miles Bader <miles@gnu.org>
Date: Mon, 26 May 1997 23:19:36 +0000
Subject: Initial checkin

---
 utils/frobauth-mod.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 177 insertions(+)
 create mode 100644 utils/frobauth-mod.c

(limited to 'utils/frobauth-mod.c')

diff --git a/utils/frobauth-mod.c b/utils/frobauth-mod.c
new file mode 100644
index 00000000..8606e783
--- /dev/null
+++ b/utils/frobauth-mod.c
@@ -0,0 +1,177 @@
+/* Modify the current authentication selected processes
+
+   Copyright (C) 1997 Free Software Foundation, Inc.
+
+   Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <error.h>
+
+#include "frobauth.h"
+
+/* For every pid in FROBAUTH, call MODIFY to change its argument UGIDS from
+   the current authentication to what it should be; CHANGE is whatever ids
+   the user specified.  If the user specifies the --verbose flags, PRINT_INFO
+   is called after successfully installing the new authentication in each
+   process, to print a message about what happened.  True is returned if no
+   errors occur, although most errors do not cause termination, and error
+   messages are printed for them.  */
+error_t
+frobauth_modify (struct frobauth *frobauth,
+		 error_t (*modify) (struct ugids *ugids,
+				    const struct ugids *change,
+				    pid_t pid, void *hook),
+		 void (*print_info) (const struct ugids *new,
+				     const struct ugids *old,
+				     const struct ugids *change,
+				     pid_t pid, void *hook),
+                 void *hook)
+{
+  int i;
+  int ok = 1;
+  pid_t cur_pid = getpid ();
+  process_t proc_server = getproc ();
+
+  /* Map MODIFY over all pids.  */
+  for (i = 0; i < frobauth->num_pids; i++)
+    if (frobauth->pids[i] != cur_pid)
+      {
+	mach_port_t msgport;
+	pid_t pid = frobauth->pids[i];
+	error_t err = proc_getmsgport (proc_server, pid, &msgport);
+
+	if (err)
+	  error (0, err, "%d: Cannot get message port", pid);
+	else
+	  {
+	    task_t task;
+
+	    err = proc_pid2task (proc_server, pid, &task);
+	    if (err)
+	      error (0, err, "%d", pid);
+	    else
+	      {
+		auth_t old_auth;
+
+		err = msg_get_init_port (msgport, task, INIT_PORT_AUTH,
+					 &old_auth);
+		if (err)
+		  error (0, err, "%d: Cannot get auth port", pid);
+		else
+		  {
+		    struct ugids old = UGIDS_INIT;
+
+		    err = ugids_merge_auth (&old, old_auth);
+
+		    if (err)
+		      error (0, err, "%d: Cannot get auth port ids", pid);
+		    else
+		      {
+			struct ugids new = UGIDS_INIT;
+
+			/* Assume all gids that can be implied by some uid are
+			   only present for that reason.  */
+			ugids_imply_all (&old);
+
+			err = ugids_set (&new, &old);
+
+			err = (*modify) (&new, &frobauth->ugids, pid, hook);
+			if (err)
+			  error (99, err, "%d: Cannot modify ids", pid);
+			else if (! ugids_equal (&new, &old))
+			  {
+			    if (! frobauth->dry_run)
+			      {
+				auth_t new_auth;
+				err =
+				  ugids_make_auth (&new, old_auth, &new_auth);
+				if (err)
+				  error (0, err,
+					 "%d: Authentication failure", pid);
+				else
+				  {
+				    err =
+				      msg_set_init_port (msgport, task,
+							 INIT_PORT_AUTH,
+							 new_auth,
+							 MACH_MSG_TYPE_MOVE_SEND);
+				    if (err)
+				      error (0, err, "%d", pid);
+				    else if (new.eff_uids.num == 0
+					     ? old.eff_uids.num > 0
+					     : (old.eff_uids.num == 0
+						|| (new.eff_uids.ids[0]
+						    != old.eff_uids.ids[0])))
+				      /* Now change the process's owner.  */
+				      {
+					process_t proc;
+					err = 
+					  proc_pid2proc (proc_server, pid,
+							 &proc);
+					if (err)
+					  error (0, err,
+						 "%d: Cannot get proc port",
+						 pid);
+					else
+					  {
+					    if (new.eff_uids.num == 0)
+					      err =
+						proc_setowner (proc, 0, 1);
+					    else
+					      err = proc_setowner
+						(proc, new.eff_uids.ids[0], 0);
+					    if (err)
+					      error
+						(0, err,
+						 "%d: Cannot set process owner",
+						 pid);
+					    mach_port_deallocate
+					      (mach_task_self (), proc);
+					  }
+				      }
+				  }
+
+			      }
+
+			    if (frobauth->verbose && !err)
+			      (*print_info) (&new, &old, &frobauth->ugids,
+					     pid, hook);
+
+			  }
+			else if (frobauth->verbose)
+			  printf ("%d: Nothing changed\n", pid);
+
+			ugids_fini (&new);
+		      }
+
+		    ugids_fini (&old);
+		    mach_port_deallocate (mach_task_self (), old_auth);
+		  }
+		mach_port_deallocate (mach_task_self (), task);	      
+	      }
+	    mach_port_deallocate (mach_task_self (), msgport);
+	  }
+
+	if (err)
+	  ok = 0;			/* Something didn't work.  */
+      }
+
+  return ok;
+}
-- 
cgit v1.2.3