diff options
Diffstat (limited to 'auth')
-rw-r--r-- | auth/ChangeLog | 184 | ||||
-rw-r--r-- | auth/Makefile | 30 | ||||
-rw-r--r-- | auth/auth.c | 504 | ||||
-rw-r--r-- | auth/auth_mig.h | 5 | ||||
-rw-r--r-- | auth/authmutations.h | 6 |
5 files changed, 729 insertions, 0 deletions
diff --git a/auth/ChangeLog b/auth/ChangeLog new file mode 100644 index 00000000..ea7f0fb4 --- /dev/null +++ b/auth/ChangeLog @@ -0,0 +1,184 @@ +1999-05-13 Roland McGrath <roland@baalperazim.frob.com> + + * auth.c (S_auth_server_authenticate, S_auth_user_authenticate): If + rendezvous port arrives as MACH_PORT_DEAD, fail with EINVAL. + +1999-05-02 Roland McGrath <roland@baalperazim.frob.com> + + * auth.c: Include <error.h>. + +1999-05-01 Roland McGrath <roland@baalperazim.frob.com> + + * auth.c (main): Give diagnostics for lack of bootstrap port or + failure of startup_authinit RPC. + +1998-11-27 Mark Kettenis <kettenis@phys.uva.nl> + + * auth.c (main): Call _hurd_proc_init with new args set to zero. + +Wed Aug 20 14:01:43 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * auth.c (main): New args for + ports_manage_port_operations_multithread. + +Wed Feb 19 23:04:30 1997 Miles Bader <miles@gnu.ai.mit.edu> + + * auth.c (argp_program_version): Make const. + +Thu Sep 12 16:27:31 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * Makefile (HURDLIBS): New variable. + (auth): Delete special depedencies. + +Thu Sep 5 11:05:37 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * auth.c (AUTH_VERSION): Delete macro. + (argp_program_version): Use STANDARD_HURD_VERSION. + (main): Pass empty string as release; HURD_VERSION as version. + +Fri Jul 19 00:35:46 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * auth.c (S_auth_makeauth): Deallocate initial reference to + NEWAUTH after *NEWHANDLE has been set. + +Thu Jul 18 19:31:53 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * auth.c (S_auth_makeauth): It's fine if a passed in auth port is + not one we know about; just make the loops across AUTHS deal + properly with null values. Only deallocate the AUTHPTS passed in + if we don't encounter any errors. Always deallocate the + references in the AUTHS array. ISUID and GROUPMEMBER functions + should check both effective and auxiliary members of AUTH. + (struct pending): Delete member `passthrough_type'. + (S_auth_user_authenticate): Always use MOVE_SEND to send pass + through port back to user. + (S_auth_server_authenticate): Don't bother initializing + U.passthrough_type or S.passthrough_type. + +Sat Jul 6 23:16:42 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * auth.c (AUTH_VERSION): New macro. + (argp_program_version): New variable. + (auth_version): Variable removed. + (main): Call argp_parse to get defaults. + Use AUTH_VERSION instead of auth_version. + <argp.h>: New include. + <idvec.h>: Changed from <hurd/idvec.h>. + +Wed Jun 26 14:22:51 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * auth.c (S_auth_makeauth): Don't special-case the 0 explicit ids + case (it used to merge in all the ids from passed in auth-handles + in that case). + +Mon May 6 14:22:13 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * auth.c (auth_version): Upgrade to 0.0. + +Sat May 4 22:40:42 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * auth.c (S_auth_user_authenticate, S_auth_server_authenticate): + Use ports_interrupt_self_on_port_death instead of + cancel_on_dead_name. Hurd_condition_wait returns a boolean, not + an error_t, so supply EINTR ourselves. + (cancel_on_dead_name): Function removed. + +Fri May 3 17:07:45 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * auth.c (S_auth_server_authenticate, S_auth_user_authenticate): + Remove IGNORED arg. + +Tue Apr 30 21:16:07 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * auth.c (S_auth_makeauth): Increment NAUTHS for first elt. + (main): Initialize the ihash tables, dammit. + +Thu Apr 25 02:57:53 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * auth.c: Rewritten. + * authmutations.h: New file. + * Makefile (LCLHDRS): Add it, remove auth_mig.h. + (OBJS): Remove auth_replyUser.o, notifyServer.o. + (auth): Depend on libports, libihash, libthreads, libshouldbeinlibc. + + * auth_mig.h: Rewritten. + * Makefile (OBJS): Add auth_replyUser.o. + +Thu Jul 6 15:29:43 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> + + * Makefile: Removed dependencies that are now automatically + generated. + +Fri Nov 18 07:34:11 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu> + + * Makefile (OBJS): Add notifyServer.o. + (auth.o): Depend on notify_S.h. + * auth.c: Include "notify_S.h". Remove _S_ from all + do_mach_notify_* server routines. + +Wed Sep 7 13:14:41 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu> + + * auth.c (isuid): Look for TEST in the uid arrays, not the gid arrays. + +Tue Sep 6 14:33:02 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu> + + * auth.c (auth_nosenders): Remove auth struct from allapts + list correctly. + +Thu Aug 25 13:24:24 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> + + * auth.c (struct saved_user): Use second rendezvous port in place + of rend_int. + (strut saved_server): Likewise. + (S_auth_user_authenticate): Replace int arg with secondary + rendezvous port. Check it instead of old rend_int for match. + Deallocate it (twice) if we are completing the auth transaction + here. Store it in U in place of the old int. + (S_auth_server_authenticate): Likewise, mutatis mutandis. + +Mon Aug 15 11:52:49 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> + + * auth.c (main): Make startup_essential_task the last thing we + do before processing messages. + +Thu Jul 21 18:39:38 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> + + * Makefile: Rewritten in accord with new scheme. + * auth.c: Include "auth_reply_U.h" instead of "auth_reply.h". + +Tue Jul 19 12:32:54 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * Makefile (auth): Don't use variable $(link) anymore. + +Tue Jul 5 14:18:23 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * Makefile (SRCS, TAGSHDRS): New variables. + +Mon Jun 20 15:04:42 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * Makefile (install): Use $(INSTALL_BIN) instead of cp. + +Thu May 19 15:18:52 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * auth.c (auth_nosenders): Take auth off of allapts list + before destroying it. + +Thu May 12 15:28:50 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * auth.c (main): Declare args ARGC and ARGV; pass ARGV in call + to _hurd_proc_init. + +Mon May 9 16:50:09 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) + + * auth.c (auth_version): New variable. + (main): Call proc_register_version. + +Thu May 5 07:42:28 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * Makefile: Change uses of $(headers) to $(includedir). + +Fri Apr 29 16:50:50 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) + + * auth.c (main): Fetch hostpriv arg and provide it to + startup_essential_task in accord with interface change to + startup.defs. diff --git a/auth/Makefile b/auth/Makefile new file mode 100644 index 00000000..da41cdd0 --- /dev/null +++ b/auth/Makefile @@ -0,0 +1,30 @@ +# Copyright (C) 1991, 93, 94, 95, 96 Free Software Foundation, Inc. +# 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 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. + +dir := auth +makemode := server + +SRCS = auth.c +OBJS = auth.o authServer.o auth_replyUser.o +LCLHDRS = authmutations.h auth_mig.h +target = auth +HURDLIBS=ports threads ihash shouldbeinlibc + +MIGSFLAGS = -imacros $(srcdir)/authmutations.h + +include ../Makeconf + diff --git a/auth/auth.c b/auth/auth.c new file mode 100644 index 00000000..dd164934 --- /dev/null +++ b/auth/auth.c @@ -0,0 +1,504 @@ +/* Authentication server. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Written by Roland McGrath. + + 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 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 <string.h> +#include <mach.h> +#include <cthreads.h> +#include <hurd.h> +#include <hurd/startup.h> +#include <hurd/ports.h> +#include <hurd/ihash.h> +#include <idvec.h> +#include <assert.h> +#include <argp.h> +#include <error.h> +#include <version.h> +#include "auth_S.h" +#include "auth_reply_U.h" + +const char *argp_program_version = STANDARD_HURD_VERSION(auth); + + +/* Auth handles are server ports with sets of ids. */ +struct authhandle + { + struct port_info pi; + struct idvec euids, egids, auids, agids; + }; + +struct port_bucket *auth_bucket; +struct port_class *authhandle_portclass; + + +/* Create a new auth port. */ + +static error_t +create_authhandle (struct authhandle **new) +{ + 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. */ + +static void +destroy_authhandle (void *p) +{ + struct authhandle *h = p; + idvec_free_contents (&h->euids); + idvec_free_contents (&h->egids); + idvec_free_contents (&h->auids); + idvec_free_contents (&h->agids); +} + +/* Called by server stub functions. */ + +authhandle_t +auth_port_to_handle (auth_t auth) +{ + return ports_lookup_port (auth_bucket, auth, authhandle_portclass); +} + +/* id management. */ + +inline void idvec_copyout (struct idvec *idvec, uid_t **ids, uid_t *nids) +{ + if (idvec->num > *nids) + *ids = idvec->ids; + else + memcpy (*ids, idvec->ids, idvec->num * sizeof *ids); + *nids = idvec->num; +} + +#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 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) + return EOPNOTSUPP; + + OUTIDS (auth); + + return 0; +} + +/* Implement auth_makeauth as described in <hurd/auth.defs>. */ +kern_return_t +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) +{ + struct authhandle *newauth, *auths[1 + nauths]; + int hasroot = 0; + error_t err; + u_int i, j; + + if (!auth) + return EOPNOTSUPP; + + auths[0] = auth; + + /* Fetch the auth structures for all the ports passed in. */ + for (i = 0; i < nauths; i++) + auths[i + 1] = auth_port_to_handle (authpts[i]); + + ++nauths; + + /* 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) \ + || idvec_contains (&(auth)->auids, uid)) +#define groupmember(gid, auth) \ + (idvec_contains (&(auth)->egids, gid) \ + || idvec_contains (&(auth)->agids, gid)) +#define isroot(auth) isuid (0, auth) + + for (i = 0; i < nauths; i++) + if (auths[i] && isroot (auths[i])) + { + hasroot = 1; + break; + } + + if (!hasroot) + { + int has_it; + + for (i = 0; i < neuids; i++) + { + has_it = 0; + for (j = 0; j < nauths; j++) + if (auths[j] && isuid (euids[i], auths[j])) + { + has_it = 1; + break; + } + if (!has_it) + goto eperm; + } + + for (i = 0; i < nauids; i++) + { + has_it = 0; + for (j = 0; j < nauths; j++) + if (auths[j] && isuid (auids[i], auths[j])) + { + has_it = 1; + break; + } + if (!has_it) + goto eperm; + } + + for (i = 0; i < negids; i++) + { + has_it = 0; + for (j = 0; j < nauths; j++) + if (auths[j] && groupmember (egids[i], auths[j])) + { + has_it = 1; + break; + } + if (!has_it) + goto eperm; + } + + for (i = 0; i < nagids; i++) + { + has_it = 0; + for (j = 0; j < nauths; j++) + if (auths[j] && groupmember (agids[i], auths[j])) + { + has_it = 1; + break; + } + if (!has_it) + goto eperm; + } + } + + err = create_authhandle (&newauth); + + /* Create a new handle with the specified ids. */ + +#define MERGE S (euids); S (egids); S (auids); S (agids); +#define S(uids) if (!err) err = idvec_merge_ids (&newauth->uids, uids, n##uids) + + MERGE; + +#undef S + + if (! err) + { + for (j = 1; j < nauths; ++j) + mach_port_deallocate (mach_task_self (), authpts[j - 1]); + *newhandle = ports_get_right (newauth); + ports_port_deref (newauth); + } + + for (j = 1; j < nauths; j++) + if (auths[j]) + ports_port_deref (auths[j]); + return err; + + eperm: + for (j = 1; j < nauths; j++) + if (auths[j]) + ports_port_deref (auths[j]); + return EPERM; +} + +/* 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; + }; + +/* Implement auth_user_authenticate as described in <hurd/auth.defs>. */ +kern_return_t +S_auth_user_authenticate (struct authhandle *userauth, + mach_port_t rendezvous, + mach_port_t *newport, + mach_msg_type_name_t *newporttype) +{ + struct pending *s; + + if (! userauth) + return EOPNOTSUPP; + + if (rendezvous == MACH_PORT_DEAD) /* Port died in transit. */ + return EINVAL; + + mutex_lock (&pending_lock); + + /* Look for this port in the server list. */ + s = ihash_find (pending_servers, rendezvous); + if (s) + { + /* Found it! Extract the port. */ + *newport = s->passthrough; + *newporttype = MACH_MSG_TYPE_MOVE_SEND; + + /* Remove it from the pending list. */ + ihash_locp_remove (pending_servers, s->locp); + + /* Give the server the auth port and wake the RPC up. + We need to add a ref in case the port dies. */ + s->user = userauth; + ports_port_ref (userauth); + + condition_signal (&s->wakeup); + mutex_unlock (&pending_lock); + + mach_port_deallocate (mach_task_self (), rendezvous); + return 0; + } + else + { + /* 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) + { + /* Store the user auth port and wait for the server RPC to wake + us up. */ + u.user = userauth; + condition_init (&u.wakeup); + ports_interrupt_self_on_port_death (userauth, rendezvous); + if (hurd_condition_wait (&u.wakeup, &pending_lock)) + /* We were interrupted; remove our record. */ + { + ihash_locp_remove (pending_users, u.locp); + err = EINTR; + } + } + /* The server side has already removed U from the ihash table. */ + mutex_unlock (&pending_lock); + + if (! err) + { + /* The server RPC has set the port and signalled U.wakeup. */ + *newport = u.passthrough; + *newporttype = MACH_MSG_TYPE_MOVE_SEND; + mach_port_deallocate (mach_task_self (), rendezvous); + } + return err; + } +} + +/* Implement auth_server_authenticate as described in <hurd/auth.defs>. */ +kern_return_t +S_auth_server_authenticate (struct authhandle *serverauth, + mach_port_t reply, + mach_msg_type_name_t reply_type, + mach_port_t rendezvous, + mach_port_t newport, + mach_msg_type_name_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 pending *u; + struct authhandle *user; + + if (! serverauth) + return EOPNOTSUPP; + + if (rendezvous == MACH_PORT_DEAD) /* Port died in transit. */ + return EINVAL; + + mutex_lock (&pending_lock); + + /* Look for this port in the user list. */ + u = ihash_find (pending_users, rendezvous); + if (u) + { + /* Remove it from the pending list. */ + ihash_locp_remove (pending_users, u->locp); + + /* Found it! We must add a ref because the one held by the + user RPC might die as soon as we unlock pending_lock. */ + user = u->user; + ports_port_ref (user); + + /* Give the user the new port and wake the RPC up. */ + u->passthrough = newport; + + condition_signal (&u->wakeup); + mutex_unlock (&pending_lock); + } + else + { + /* 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; + condition_init (&s.wakeup); + ports_interrupt_self_on_port_death (serverauth, rendezvous); + if (hurd_condition_wait (&s.wakeup, &pending_lock)) + /* We were interrupted; remove our record. */ + { + ihash_locp_remove (pending_servers, s.locp); + err = EINTR; + } + } + /* The user side has already removed S from the ihash table. */ + mutex_unlock (&pending_lock); + + if (err) + return err; + + /* The user RPC has set the port (with a ref) and signalled S.wakeup. */ + user = s.user; + } + + /* Extract the ids. We must use a separate reply stub so + we can deref the user auth handle after the reply uses its + contents. */ + auth_server_authenticate_reply (reply, reply_type, 0, + user->euids.ids, user->euids.num, + user->auids.ids, user->auids.num, + user->egids.ids, user->egids.num, + user->agids.ids, user->agids.num); + ports_port_deref (user); + mach_port_deallocate (mach_task_self (), rendezvous); + return MIG_NO_REPLY; +} + + + +static int +auth_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) +{ + 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)); +} + + +int +main (int argc, char **argv) +{ + error_t err; + mach_port_t boot; + process_t proc; + mach_port_t hostpriv, masterdev; + struct authhandle *firstauth; + + argp_parse (0, argc, argv, 0, 0, 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. */ + err = task_get_bootstrap_port (mach_task_self (), &boot); + assert_perror (err); + if (boot == MACH_PORT_NULL) + error (2, 0, "auth server can only be run by init during boot"); + err = startup_authinit (boot, ports_get_right (firstauth), + MACH_MSG_TYPE_MAKE_SEND, &proc); + if (err) + error (2, err, "cannot contact init for bootstrap"); + + /* Register ourselves with the proc server and then start signals. */ + proc_getprivports (proc, &hostpriv, &masterdev); + proc_register_version (proc, hostpriv, "auth", "", HURD_VERSION); + mach_port_deallocate (mach_task_self (), masterdev); + _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], proc); + _hurd_proc_init (argv, NULL, 0); + + /* 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); + + /* Allocate the hash tables. */ + err = ihash_create (&pending_users); + assert_perror (err); + err = ihash_create (&pending_servers); + assert_perror (err); + + /* Be a server. */ + while (1) + ports_manage_port_operations_multithread (auth_bucket, + auth_demuxer, + 30 * 1000, 0, 0); +} diff --git a/auth/auth_mig.h b/auth/auth_mig.h new file mode 100644 index 00000000..d919c1b9 --- /dev/null +++ b/auth/auth_mig.h @@ -0,0 +1,5 @@ +typedef struct authhandle *authhandle_t; + +authhandle_t auth_port_to_handle (auth_t); + +#include <hurd/ports.h> diff --git a/auth/authmutations.h b/auth/authmutations.h new file mode 100644 index 00000000..63b2f540 --- /dev/null +++ b/auth/authmutations.h @@ -0,0 +1,6 @@ +/* CPP definitions for MiG processing of auth.defs for auth server. */ + +#define AUTH_INTRAN authhandle_t auth_port_to_handle (auth_t) +#define AUTH_DESTRUCTOR ports_port_deref (authhandle_t) + +#define AUTH_IMPORTS import "auth_mig.h"; |