summaryrefslogtreecommitdiff
path: root/auth
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-04-25 07:25:58 +0000
committerRoland McGrath <roland@gnu.org>1996-04-25 07:25:58 +0000
commit8598722868278021a84b4e9145f5da0e573c8b51 (patch)
treeeebf8b0e27d6e8f0238ab6df61717c75755bd603 /auth
parent0d302c36ee18b7bdf7ba34abbbc68c2b8e4b87c0 (diff)
Rewritten.
Diffstat (limited to 'auth')
-rw-r--r--auth/auth.c832
1 files changed, 322 insertions, 510 deletions
diff --git a/auth/auth.c b/auth/auth.c
index ced121fc..fb20392f 100644
--- a/auth/auth.c
+++ b/auth/auth.c
@@ -1,381 +1,164 @@
-/* Authentication server
- Copyright (C) 1992, 1993, 1994 Free Software Foundation
+/* Authentication server.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Roland McGrath.
-This file is part of the GNU Hurd.
+ This file is part of the GNU Hurd.
-The GNU Hurd 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.
+ The GNU Hurd 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.
-The GNU Hurd 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.
+ The GNU Hurd 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 the GNU Hurd; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ 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. */
-/* Written by Michael I. Bushnell. */
-
-#include "auth_S.h"
-#include "auth_reply_U.h"
-#include "notify_S.h"
-#include <hurd/startup.h>
-#include <mach/error.h>
-#include <errno.h>
-#include <mach/mig_errors.h>
-#include <mach/notify.h>
#include <stdlib.h>
-#include <hurd.h>
-#include <mach.h>
#include <string.h>
+#include <mach.h>
+#include <cthreads.h>
+#include <hurd.h>
+#include <hurd/startup.h>
+#include <hurd/ports.h>
+#include <hurd/idvec.h>
+#include <hurd/ihash.h>
+#include <assert.h>
+#include "auth_S.h"
-/* This represents a request from a call to auth_user_authenticate
- which is waiting for the corresponding call. */
-struct saved_user
-{
- struct saved_user *next; /* hash link */
-
- mach_port_t rendezvous; /* rendezvous port */
- mach_port_t rendezvous2; /* secondary rendezvous port */
-
- struct apt *userid; /* to be passed to server */
-
- mach_port_t reply; /* where to send the answer */
- mach_msg_type_name_t reply_type; /* type of reply port */
-};
-
-/* This represents a request from a call to auth_server_authenticate
- which is waiting for the corresponding call. */
-struct saved_server
-{
- struct saved_server *next; /* hash link */
-
- mach_port_t rendezvous; /* rendezvous port */
- mach_port_t rendezvous2; /* secondary rendezvous port */
-
- struct apt *server; /* who made the call? */
- mach_port_t passthrough; /* new port to be given to user */
-
- mach_port_t reply; /* where to send the answer */
- mach_msg_type_name_t reply_type; /* type of reply port */
-};
-
-struct saved_user *userlist;
-struct saved_server *serverlist;
-
-struct apt
-{
- mach_port_t port;
- uid_t *gen_uids, *aux_uids;
- uid_t *gen_gids, *aux_gids;
- int ngen_uids, naux_uids, ngen_gids, naux_gids;
- struct apt *next, **prevp;
-};
-
-struct apt *allapts;
-
-struct apt *getauthstruct (void);
-void auth_nosenders (struct apt *);
-
-mach_port_t auth_pset;
-
-/* Our version number */
char *auth_version = "0.0 pre-alpha";
-
-/* Demultiplex an incoming message. */
-int
-request_server (mach_msg_header_t *inp,
- mach_msg_header_t *outp)
-{
- extern int auth_server (), notify_server ();
-
- return (auth_server (inp, outp)
- || notify_server (inp, outp));
-
-}
-
-void
-main (int argc, char **argv)
-{
- mach_port_t boot;
- struct apt *firstauth;
- process_t proc;
- extern int mach_msg_server ();
- mach_port_t hostpriv, masterdev;
-
- mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET,
- &auth_pset);
-
- task_get_bootstrap_port (mach_task_self (), &boot);
-
- firstauth = getauthstruct ();
- firstauth->gen_uids = malloc (sizeof (uid_t) * 1);
- firstauth->aux_uids = malloc (sizeof (uid_t) * 2);
- firstauth->gen_gids = malloc (sizeof (uid_t) * 1);
- firstauth->aux_gids = malloc (sizeof (uid_t) * 2);
- firstauth->gen_uids[0] = 0;
- firstauth->aux_uids[0] = firstauth->aux_uids[1] = 0;
- firstauth->gen_gids[0] = 0;
- firstauth->aux_gids[0] = firstauth->aux_gids[1] = 0;
- firstauth->ngen_uids = firstauth->ngen_gids = 1;
- firstauth->naux_uids = firstauth->naux_gids = 2;
-
- startup_authinit (boot, firstauth->port, MACH_MSG_TYPE_MAKE_SEND, &proc);
- proc_getprivports (proc, &hostpriv, &masterdev);
- proc_register_version (proc, hostpriv, "auth", HURD_RELEASE, auth_version);
- mach_port_deallocate (mach_task_self (), masterdev);
- _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], proc);
- _hurd_proc_init (argv);
- /* Init knows intimately that we will be ready for messages
- as soon as this returns. */
- startup_essential_task (boot, mach_task_self (), MACH_PORT_NULL, "auth",
- hostpriv);
- mach_port_deallocate (mach_task_self (), boot);
- mach_port_deallocate (mach_task_self (), hostpriv);
+/* Auth handles are server ports with sets of ids. */
+struct authhandle
+ {
+ struct port_info pi;
+ struct idvec euids, egids, auids, agids;
+ };
- while (1)
- mach_msg_server (request_server, vm_page_size * 2, auth_pset);
-}
+struct port_bucket *auth_bucket;
+struct port_class *authhandle_portclass;
-/* Server routines: */
-
-/* Called when an auth port has no more senders. */
-error_t
-do_mach_notify_no_senders (mach_port_t notify,
- mach_port_mscount_t mscount)
-{
- auth_nosenders (convert_auth_to_apt (notify));
- return 0;
-}
+/* Create a new auth port. */
-/* A given auth handle has no more senders; deallocate all state referring
- to this handle. */
-void
-auth_nosenders (struct apt *auth)
+static error_t
+create_authhandle (struct authhandle **new)
{
- /* Remove all references to this from the saved lists */
- {
- struct saved_user *s, **prevp, *tmp;
- for (s = userlist, prevp = &userlist; s;)
- {
- if (s->userid == auth)
- {
- *prevp = s->next;
- tmp = s;
- prevp = &s->next;
- s = s->next;
-
- mach_port_deallocate (mach_task_self (), tmp->rendezvous);
- mach_port_deallocate (mach_task_self (), tmp->reply);
- free (tmp);
- }
- else
- {
- prevp = &s->next;
- s = s->next;
- }
- }
- }
- {
- struct saved_server *s, **prevp, *tmp;
- for (s = serverlist, prevp = &serverlist; s;)
- {
- if (s->server == auth)
- {
- *prevp = s->next;
- tmp = s;
- prevp = &s->next;
- s = s->next;
-
- mach_port_deallocate (mach_task_self (), tmp->rendezvous);
- mach_port_deallocate (mach_task_self (), tmp->reply);
- if (tmp->passthrough)
- mach_port_deallocate (mach_task_self (), tmp->passthrough);
- free (tmp);
- }
- else
- {
- prevp = &s->next;
- s = s->next;
- }
- }
- }
-
- /* Take off allapts list */
- *auth->prevp = auth->next;
- if (auth->next)
- auth->next->prevp = auth->prevp;
-
- /* Delete its storage and port. */
- mach_port_mod_refs (mach_task_self (), auth->port,
- MACH_PORT_RIGHT_RECEIVE, -1);
- free (auth->gen_uids);
- free (auth->aux_uids);
- free (auth->gen_gids);
- free (auth->aux_gids);
- free (auth);
+ error_t err = ports_create_port (authhandle_portclass, auth_bucket,
+ sizeof **new, new);
+ if (! err)
+ bzero (&(*new)->euids, (void *) &(*new)[1] - (void *) &(*new)->euids);
+ return err;
}
+/* Clean up a dead auth port. */
-/* Return true iff TEST is a genuine or auxiliary group id in AUTH. */
-inline int
-groupmember (gid_t test,
- struct apt *auth)
+static void
+destroy_authhandle (void *p)
{
- int i;
-
- for (i = 0; i < auth->ngen_gids; i++)
- if (test == auth->gen_gids[i])
- return 1;
- for (i = 0; i < auth->naux_gids; i++)
- if (test == auth->aux_gids[i])
- return 1;
- return 0;
+ struct authhandle *h = p;
+ idvec_free_contents (&h->euids);
+ idvec_free_contents (&h->egids);
+ idvec_free_contents (&h->auids);
+ idvec_free_contents (&h->agids);
}
-/* Return true iff TEST is a genuine or auxiliary uid in AUTH. */
-inline int
-isuid (uid_t test,
- struct apt *auth)
-{
- int i;
-
- for (i = 0; i < auth->ngen_uids; i++)
- if (test == auth->gen_uids[i])
- return 1;
- for (i = 0; i < auth->naux_uids; i++)
- if (test == auth->aux_uids[i])
- return 1;
- return 0;
-}
+/* Called by server stub functions. */
-/* Return true if the the given auth handle is root (uid 0). */
-inline int
-isroot (struct apt *idblock)
+authhandle_t
+auth_port_to_handle (auth_t auth)
{
- return isuid (0, idblock);
+ return ports_lookup_port (auth_bucket, auth, authhandle_portclass);
}
+
+/* id management. */
-/* Allocate a new auth handle, complete with port. */
-struct apt *
-getauthstruct ()
+inline void idvec_copyout (struct idvec *idvec, uid_t **ids, uid_t *nids)
{
- struct apt *newauth;
- mach_port_t unused;
-
- newauth = malloc (sizeof (struct apt));
- mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
- &newauth->port);
- mach_port_request_notification (mach_task_self (), newauth->port,
- MACH_NOTIFY_NO_SENDERS, 1, newauth->port,
- MACH_MSG_TYPE_MAKE_SEND_ONCE, &unused);
- mach_port_move_member (mach_task_self (), newauth->port, auth_pset);
- newauth->next = allapts;
- if (newauth->next)
- newauth->next->prevp = &newauth->next;
- newauth->prevp = &allapts;
- allapts = newauth;
- return newauth;
+ if (idvec->num > *nids)
+ *ids = idvec->ids;
+ *nids = idvec->num;
}
-
-
-/* Client requests */
+#define C(auth, ids) idvec_copyout (&auth->ids, ids, n##ids)
+#define OUTIDS(auth) (C (auth, euids), C (auth, egids), \
+ C (auth, auids), C (auth, agids))
/* Implement auth_getids as described in <hurd/auth.defs>. */
kern_return_t
-S_auth_getids (struct apt *auth,
- uid_t **gen_uids,
- u_int *ngen_uids,
- uid_t **aux_uids,
- u_int *naux_uids,
- uid_t **gen_gids,
- u_int *ngen_gids,
- uid_t **aux_gids,
- u_int *naux_gids)
+S_auth_getids (struct authhandle *auth,
+ uid_t **euids,
+ u_int *neuids,
+ uid_t **auids,
+ u_int *nauids,
+ uid_t **egids,
+ u_int *negids,
+ uid_t **agids,
+ u_int *nagids)
{
- if (!auth)
+ if (! auth)
return EOPNOTSUPP;
-
- if (auth->ngen_uids > *ngen_uids)
- *gen_uids = auth->gen_uids;
- else
- bcopy (auth->gen_uids, *gen_uids, sizeof (uid_t) * auth->ngen_uids);
- *ngen_uids = auth->ngen_uids;
- if (auth->naux_uids > *naux_uids)
- *aux_uids = auth->aux_uids;
- else
- bcopy (auth->aux_uids, *aux_uids, sizeof (uid_t) * auth->naux_uids);
- *naux_uids = auth->naux_uids;
-
- if (auth->ngen_gids > *ngen_gids)
- *gen_gids = auth->gen_gids;
- else
- bcopy (auth->gen_gids, *gen_gids, sizeof (uid_t) * auth->ngen_gids);
- *ngen_gids = auth->ngen_gids;
-
- if (auth->naux_gids > *naux_gids)
- *aux_gids = auth->aux_gids;
- else
- bcopy (auth->aux_gids, *aux_gids, sizeof (uid_t) * auth->naux_gids);
- *naux_gids = auth->naux_gids;
+ OUTIDS (auth);
return 0;
}
/* Implement auth_makeauth as described in <hurd/auth.defs>. */
kern_return_t
-S_auth_makeauth (struct apt *auth,
- mach_port_t *authpts,
- u_int nauths,
- uid_t *gen_uids,
- u_int ngen_uids,
- uid_t *aux_uids,
- u_int naux_uids,
- uid_t *gen_gids,
- u_int ngen_gids,
- uid_t *aux_gids,
- u_int naux_gids,
+S_auth_makeauth (struct authhandle *auth,
+ mach_port_t *authpts, u_int nauths,
+ uid_t *euids, u_int neuids,
+ uid_t *auids, u_int nauids,
+ uid_t *egids, u_int negids,
+ uid_t *agids, u_int nagids,
mach_port_t *newhandle)
{
- int i, j;
- struct apt *newauth;
- struct apt **auths = alloca ((nauths + 1) * sizeof (struct apt *));
+ struct authhandle *newauth, *auths[1 + nauths];
int hasroot = 0;
+ error_t err;
+ u_int i, j;
if (!auth)
return EOPNOTSUPP;
+
auths[0] = auth;
+ /* Verify all the auth ports passed in. */
for (i = 0; i < nauths; i++)
- if (!(auths[i + 1] = convert_auth_to_apt (authpts[i])))
+ if (!(auths[i + 1] = auth_port_to_handle (authpts[i])))
return EINVAL;
- nauths++;
+ nauths = i;
+
+ /* Verify that the union of the handles passed in either contains euid 0
+ (root), or contains all the requested ids. */
+
+#define isuid(uid, auth) idvec_contains (&(auth)->euids, uid)
+#define groupmember(gid, auth) idvec_contains (&(auth)->egids, gid)
+#define isroot(auth) isuid (0, auth)
for (i = 0; i < nauths; i++)
- if (isroot (auth))
+ if (isroot (auths[i]))
{
hasroot = 1;
break;
}
-
+
if (!hasroot)
{
int has_it;
-
- for (i = 0; i < ngen_uids; i++)
+
+ for (i = 0; i < neuids; i++)
{
has_it = 0;
for (j = 0; j < nauths; j++)
- if (isuid (gen_uids[i], auths[j]))
+ if (isuid (euids[i], auths[j]))
{
has_it = 1;
break;
@@ -383,12 +166,12 @@ S_auth_makeauth (struct apt *auth,
if (!has_it)
return EPERM;
}
-
- for (i = 0; i < naux_uids; i++)
+
+ for (i = 0; i < nauids; i++)
{
has_it = 0;
for (j = 0; j < nauths; j++)
- if (isuid (aux_uids[i], auths[j]))
+ if (isuid (auids[i], auths[j]))
{
has_it = 1;
break;
@@ -396,12 +179,12 @@ S_auth_makeauth (struct apt *auth,
if (!has_it)
return EPERM;
}
-
- for (i = 0; i < ngen_gids; i++)
+
+ for (i = 0; i < negids; i++)
{
has_it = 0;
for (j = 0; j < nauths; j++)
- if (groupmember (gen_gids[i], auths[j]))
+ if (groupmember (egids[i], auths[j]))
{
has_it = 1;
break;
@@ -409,12 +192,12 @@ S_auth_makeauth (struct apt *auth,
if (!has_it)
return EPERM;
}
-
- for (i = 0; i < naux_gids; i++)
+
+ for (i = 0; i < nagids; i++)
{
has_it = 0;
for (j = 0; j < nauths; j++)
- if (groupmember (aux_gids[i], auths[j]))
+ if (groupmember (agids[i], auths[j]))
{
has_it = 1;
break;
@@ -422,232 +205,261 @@ S_auth_makeauth (struct apt *auth,
if (!has_it)
return EPERM;
}
- }
+ }
- for (j = 0; j < nauths - 1; j++)
+ for (j = 1; j < nauths; ++j)
mach_port_deallocate (mach_task_self (), authpts[j]);
- newauth = getauthstruct ();
- newauth->gen_uids = malloc (sizeof (uid_t) * ngen_uids);
- newauth->aux_uids = malloc (sizeof (uid_t) * naux_uids);
- newauth->gen_gids = malloc (sizeof (uid_t) * ngen_gids);
- newauth->aux_gids = malloc (sizeof (uid_t) * naux_gids);
- newauth->ngen_uids = ngen_uids;
- newauth->naux_uids = naux_uids;
- newauth->ngen_gids = ngen_gids;
- newauth->naux_gids = naux_gids;
- bcopy (gen_uids, newauth->gen_uids, ngen_uids * sizeof (uid_t));
- bcopy (aux_uids, newauth->aux_uids, naux_uids * sizeof (uid_t));
- bcopy (gen_gids, newauth->gen_gids, ngen_gids * sizeof (uid_t));
- bcopy (aux_gids, newauth->aux_gids, naux_gids * sizeof (uid_t));
-
- *newhandle = newauth->port;
- return 0;
+ err = create_authhandle (&newauth);
+ if (err)
+ return err;
+
+#define MERGE S (euids); S (egids); S (auids); S (agids);
+ if (neuids || nauids || negids || nagids)
+ {
+ /* Create a new handle with the specified ids. */
+
+#define S(uids) if (!err) err = idvec_merge_ids (&newauth->uids, uids, n##uids)
+ MERGE;
+#undef S
+ }
+ else
+ {
+ /* Use the union of the ids of the passed in handles for the new one. */
+
+ for (i = 0; !err && i < nauths; ++i)
+ {
+#define S(uids) if (!err) err = idvec_merge (&newauth->uids, &auths[i]->uids)
+ MERGE;
+#undef S
+ }
+ }
+
+ if (! err)
+ *newhandle = ports_get_right (newauth);
+
+ return err;
+}
+
+/* Transaction handling. */
+
+/* Table of pending transactions keyed on RENDEZVOUS. */
+struct ihash *pending_users, *pending_servers;
+struct mutex pending_lock = MUTEX_INITIALIZER;
+
+/* A pending transaction. */
+struct pending
+ {
+ void **locp; /* Position in one of the ihash tables. */
+ struct condition wakeup; /* The waiter is blocked on this condition. */
+
+ /* The user's auth handle. */
+ struct authhandle *user;
+
+ /* The port to pass back to the user. */
+ mach_port_t passthrough;
+ mach_msg_type_name_t passthrough_type;
+ };
+
+
+/* Request dead-name notification on RENDEZVOUS and arrange that
+ the current thread be cancelled should it die. */
+static void
+cancel_on_dead_name (struct authhandle *auth, mach_port_t rendezvous)
+{
+ mach_port_t foo;
+ mach_port_request_notification (mach_task_self (), rendezvous,
+ MACH_NOTIFY_DEAD_NAME, 1,
+ auth->pi.port_right,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
+ if (foo != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), foo);
+ ports_interrupt_self_on_port_death (auth, rendezvous);
}
+
/* Implement auth_user_authenticate as described in <hurd/auth.defs>. */
kern_return_t
-S_auth_user_authenticate (struct apt *userauth,
- mach_port_t reply,
- mach_msg_type_name_t reply_porttype,
+S_auth_user_authenticate (struct authhandle *userauth,
+ mach_port_t ignored,
mach_port_t rendezvous,
- mach_port_t rendezvous2,
mach_port_t *newport,
mach_msg_type_name_t *newporttype)
{
- struct saved_server *sv, **spp;
- struct saved_user *u;
-
- if (!userauth)
- return EOPNOTSUPP;
-
+ struct pending *s;
+
+ mutex_lock (&pending_lock);
+
/* Look for this port in the server list. */
- for (sv = serverlist, spp = &serverlist; sv;)
+ s = ihash_find (pending_servers, rendezvous);
+ if (s)
+ {
+ /* Found it! Extract the port. */
+ *newport = s->passthrough;
+ *newporttype = s->passthrough_type;
+
+ /* Remove it from the pending list. */
+ ihash_locp_remove (pending_servers, s->locp);
+
+ /* Give the server the auth port and wake the RPC up. */
+ s->user = userauth;
+ mutex_unlock (&pending_lock);
+ condition_signal (&s->wakeup);
+
+ return 0;
+ }
+ else
{
- if (sv->rendezvous == rendezvous && sv->rendezvous2 == rendezvous2)
+ /* No pending server RPC for this port.
+ Create a pending user RPC record. */
+ struct pending u;
+ error_t err;
+
+ err = ihash_add (pending_users, rendezvous, &u, &u.locp);
+ if (! err)
{
- *spp = sv->next;
- break;
+ /* Store the user auth port and wait for the server RPC to wake
+ us up. */
+ u.user = userauth;
+ condition_init (&u.wakeup);
+ cancel_on_dead_name (userauth, rendezvous);
+ err = hurd_condition_wait (&u.wakeup, &pending_lock);
}
- else
+ /* The server side has already removed U from the ihash table. */
+ mutex_unlock (&pending_lock);
+
+ if (! err)
{
- spp = &sv->next;
- sv = sv->next;
+ /* The server RPC has set the port and signalled U.wakeup. */
+ *newport = u.passthrough;
+ *newporttype = u.passthrough_type;
}
+ return err;
}
-
- if (sv)
- {
- *newport = sv->passthrough;
- *newporttype = MACH_MSG_TYPE_MOVE_SEND;
- auth_server_authenticate_reply (sv->reply, sv->reply_type, 0,
- userauth->gen_uids, userauth->ngen_uids,
- userauth->aux_uids, userauth->naux_uids,
- userauth->gen_gids, userauth->ngen_uids,
- userauth->aux_gids, userauth->naux_uids);
- free (sv);
-
- /* Drop both rights from the call. */
- mach_port_mod_refs (mach_task_self (), rendezvous, MACH_PORT_RIGHT_SEND,
- -2);
- mach_port_mod_refs (mach_task_self (), rendezvous2, MACH_PORT_RIGHT_SEND,
- -2);
- return 0;
- }
-
- /* User got here first. */
- u = malloc (sizeof (struct saved_user));
-
- u->rendezvous = rendezvous;
- u->rendezvous2 = rendezvous2;
- u->userid = userauth;
-
- u->reply = reply;
- u->reply_type = reply_porttype;
-
- u->next = userlist;
- userlist = u;
-
- return MIG_NO_REPLY;
}
/* Implement auth_server_authenticate as described in <hurd/auth.defs>. */
kern_return_t
-S_auth_server_authenticate (struct apt *serverauth,
- mach_port_t reply,
- mach_msg_type_name_t reply_porttype,
+S_auth_server_authenticate (struct authhandle *serverauth,
+ mach_port_t ignored,
mach_port_t rendezvous,
- mach_port_t rendezvous2,
mach_port_t newport,
- uid_t **gen_uids,
- u_int *ngen_uids,
- uid_t **aux_uids,
- u_int *naux_uids,
- uid_t **gen_gids,
- u_int *ngen_gids,
- uid_t **aux_gids,
- u_int *naux_gids)
+ mach_port_t newport_type,
+ uid_t **euids,
+ u_int *neuids,
+ uid_t **auids,
+ u_int *nauids,
+ uid_t **egids,
+ u_int *negids,
+ uid_t **agids,
+ u_int *nagids)
{
- struct saved_user *su, **sup;
- struct saved_server *v;
- struct apt *uauth;
-
- if (!serverauth)
- return EOPNOTSUPP;
+ struct pending *u;
+
+ mutex_lock (&pending_lock);
/* Look for this port in the user list. */
- for (su = userlist, sup = &userlist; su;)
+ u = ihash_find (pending_users, rendezvous);
+ if (u)
{
- if (su->rendezvous == rendezvous && su->rendezvous2 == rendezvous2)
- {
- *sup = su->next;
- break;
- }
- else
- {
- sup = &su->next;
- su = su->next;
- }
+ /* Found it! Extract the ids. */
+ OUTIDS (u->user);
+
+ /* Remove it from the pending list. */
+ ihash_locp_remove (pending_users, u->locp);
+
+ /* Give the user the new port and wake the RPC up. */
+ u->passthrough = newport;
+ u->passthrough_type = newport_type;
+ mutex_unlock (&pending_lock);
+ condition_signal (&u->wakeup);
+
+ return 0;
}
- if (su)
+ else
{
- auth_user_authenticate_reply (su->reply, su->reply_type, 0, newport,
- MACH_MSG_TYPE_MOVE_SEND);
-
- uauth = su->userid;
-
- if (uauth->ngen_uids > *ngen_uids)
- *gen_uids = uauth->gen_uids;
- else
- bcopy (uauth->gen_uids, *gen_uids, sizeof (uid_t) * uauth->ngen_uids);
- *ngen_uids = uauth->ngen_uids;
-
- if (uauth->naux_uids > *naux_uids)
- *aux_uids = uauth->aux_uids;
- else
- bcopy (uauth->aux_uids, *aux_uids, sizeof (uid_t) * uauth->naux_uids);
- *naux_uids = uauth->naux_uids;
-
- if (uauth->ngen_gids > *ngen_gids)
- *gen_gids = uauth->gen_gids;
- else
- bcopy (uauth->gen_gids, *gen_gids, sizeof (uid_t) * uauth->ngen_gids);
- *ngen_gids = uauth->ngen_gids;
-
- if (uauth->naux_gids > *naux_gids)
- *aux_gids = uauth->aux_gids;
- else
- bcopy (uauth->aux_gids, *aux_gids, sizeof (uid_t) * uauth->naux_gids);
- *naux_gids = uauth->naux_gids;
-
- free (su);
-
- mach_port_mod_refs (mach_task_self (), rendezvous, MACH_PORT_RIGHT_SEND,
- -2);
- mach_port_mod_refs (mach_task_self (), rendezvous2, MACH_PORT_RIGHT_SEND,
- -2);
- return 0;
+ /* No pending user RPC for this port.
+ Create a pending server RPC record. */
+ struct pending s;
+ error_t err;
+
+ err = ihash_add (pending_servers, rendezvous, &s, &s.locp);
+ if (! err)
+ {
+ /* Store the new port and wait for the user RPC to wake us up. */
+ s.passthrough = newport;
+ s.passthrough_type = newport_type;
+ condition_init (&s.wakeup);
+ cancel_on_dead_name (serverauth, rendezvous);
+ err = hurd_condition_wait (&s.wakeup, &pending_lock);
+ }
+ /* The user side has already removed S from the ihash table. */
+ mutex_unlock (&pending_lock);
+
+ if (! err)
+ /* The user RPC has set the port and signalled S.wakeup. */
+ OUTIDS (s.user);
+
+ return err;
}
-
- /* Server got here first. */
- v = malloc (sizeof (struct saved_server));
-
- v->rendezvous = rendezvous;
- v->rendezvous2 = rendezvous2;
- v->passthrough = newport;
-
- v->reply = reply;
- v->reply_type = reply_porttype;
-
- v->next = serverlist;
- serverlist = v;
-
- return MIG_NO_REPLY;
}
-/* Convert an auth port into an auth handle structure. */
-struct apt *
-convert_auth_to_apt (auth_t auth)
-{
- struct apt *a;
- for (a = allapts; a; a = a->next)
- if (a->port == auth)
- return a;
- return 0;
-}
-/* Unneeded notification stubs: */
-kern_return_t
-do_mach_notify_port_deleted (mach_port_t notify,
- mach_port_t name)
-{
- return 0;
-}
-kern_return_t
-do_mach_notify_msg_accepted (mach_port_t notify,
- mach_port_t name)
+static int
+auth_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
{
- return 0;
+ extern int auth_server (mach_msg_header_t *inp, mach_msg_header_t *outp);
+ return (auth_server (inp, outp) ||
+ ports_interrupt_server (inp, outp) ||
+ ports_notify_server (inp, outp));
}
-kern_return_t
-do_mach_notify_port_destroyed (mach_port_t notify,
- mach_port_t name)
-{
- return 0;
-}
-kern_return_t
-do_mach_notify_send_once (mach_port_t notify)
+int
+main (int argc, char **argv)
{
- return 0;
-}
+ error_t err;
+ mach_port_t boot;
+ process_t proc;
+ mach_port_t hostpriv, masterdev;
+ struct authhandle *firstauth;
-kern_return_t
-do_mach_notify_dead_name (mach_port_t notify,
- mach_port_t name)
-{
- return 0;
-}
+ auth_bucket = ports_create_bucket ();
+ authhandle_portclass = ports_create_class (&destroy_authhandle, 0);
+
+ /* Create the initial root auth handle. */
+ err = create_authhandle (&firstauth);
+ assert_perror (err);
+ idvec_add (&firstauth->euids, 0);
+ idvec_add (&firstauth->auids, 0);
+ idvec_add (&firstauth->auids, 0);
+ idvec_merge (&firstauth->egids, &firstauth->euids);
+ idvec_merge (&firstauth->agids, &firstauth->auids);
+
+ /* Fetch our bootstrap port and contact the bootstrap filesystem. */
+ task_get_bootstrap_port (mach_task_self (), &boot);
+ startup_authinit (boot, ports_get_right (firstauth),
+ MACH_MSG_TYPE_MAKE_SEND, &proc);
+
+ /* Register ourselves with the proc server and then start signals. */
+ proc_getprivports (proc, &hostpriv, &masterdev);
+ proc_register_version (proc, hostpriv, "auth", HURD_RELEASE, auth_version);
+ mach_port_deallocate (mach_task_self (), masterdev);
+ _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], proc);
+ _hurd_proc_init (argv);
+ /* Init knows intimately that we will be ready for messages
+ as soon as this returns. */
+ startup_essential_task (boot, mach_task_self (), MACH_PORT_NULL, "auth",
+ hostpriv);
+ mach_port_deallocate (mach_task_self (), boot);
+ mach_port_deallocate (mach_task_self (), hostpriv);
+
+ /* Be a server. */
+ while (1)
+ ports_manage_port_operations_multithread (auth_bucket,
+ auth_demuxer,
+ 30 * 1000, 0,
+ 0, MACH_PORT_NULL);
+}