diff options
-rw-r--r-- | auth/auth.c | 832 |
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); +} |