diff options
author | Miles Bader <miles@gnu.org> | 1997-09-29 22:11:56 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 1997-09-29 22:11:56 +0000 |
commit | 5c171367f19d225eb58989d163121d514a9c757d (patch) | |
tree | cf95bc44c76f60f966574379e8b9c70b25efb7e5 /libshouldbeinlibc | |
parent | 1f1c8307ffc89a28ed0721a35854caf36429a231 (diff) |
Initial checkin
Diffstat (limited to 'libshouldbeinlibc')
-rw-r--r-- | libshouldbeinlibc/ugids-verify-auth.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/libshouldbeinlibc/ugids-verify-auth.c b/libshouldbeinlibc/ugids-verify-auth.c new file mode 100644 index 00000000..f55f4a02 --- /dev/null +++ b/libshouldbeinlibc/ugids-verify-auth.c @@ -0,0 +1,191 @@ +/* Verify user/group passwords and authenticate accordingly + + Copyright (C) 1997 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.ai.mit.edu> + 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <stdlib.h> +#include <string.h> +#include <hurd.h> +#include <ctype.h> +#include <unistd.h> +#include <argp.h> +#include <pwd.h> +#include <grp.h> + +#include <hurd/paths.h> +#include <hurd/password.h> + +#include "ugids.h" + +/* XXXX these are dummies to use until libc gets re-installed. */ +error_t +password_check_user (io_t a, uid_t b, const char *c, auth_t *d) +{ + return ENOSYS; +} +error_t +password_check_group (io_t a, uid_t b, const char *c, auth_t *d) +{ + return ENOSYS; +} + +/* Accumulated information from authentication various passwords. */ +struct svma_state +{ + /* The password server. */ + file_t server; + + /* An auth port for each password that was verify by the server. */ + auth_t *auths; + size_t num_auths; +}; + +/* Append the auth ports in AUTHS, of length NUM_AUTHS, to the auth port + vector in SS, returning 0 if successful, or an error. */ +static error_t +svma_state_add_auths (struct svma_state *ss, const auth_t *auths, size_t num_auths) +{ + auth_t *new = realloc (ss->auths, ss->num_auths + num_auths); + if (new) + { + ss->auths = new; + while (num_auths--) + ss->auths[ss->num_auths++] = *auths++; + return 0; + } + else + return ENOMEM; +} + +/* Get authentication from PASSWORD using the hurd password server. */ +static error_t +server_verify_make_auth (const char *password, + uid_t id, int is_group, + void *pwd_or_grp, void *hook) +{ + auth_t auth; + struct svma_state *svma_state = hook; + error_t (*check) (io_t server, uid_t id, const char *passwd, auth_t *auth) = + is_group ? password_check_user : password_check_group; + error_t err = (*check) (svma_state->server, id, password, &auth); + + if (! err) + /* PASSWORD checked out ok; the corresponding authentication is in AUTH. */ + { + err = svma_state_add_auths (svma_state, &auth, 1); + if (err) + mach_port_deallocate (mach_task_self (), auth); + } + + return err; +} + +/* Verify that we have the right to the ids in UGIDS, given that we already + possess those in HAVE_UIDS and HAVE_GIDS (asking for passwords where + necessary), and return corresponding authentication in AUTH; the auth + ports in FROM, of length NUM_FROM, are used to supplement the auth port of + the current process if necessary. 0 is returned if access should be + allowed, otherwise EINVAL if an incorrect password was entered, or an + error relating to resource failure. GETPASS_FN and GETPASS_HOOK are as + for the idvec_verify function in <idvec.h>. */ +error_t +ugids_verify_make_auth (const struct ugids *ugids, + const struct idvec *have_uids, const struct idvec *have_gids, + char *(*getpass_fn) (const char *prompt, + uid_t id, int is_group, + void *pwd_or_grp, void *hook), + void *getpass_hook, + const auth_t *from, size_t num_from, + auth_t *auth) +{ + error_t err; + /* By default, get authentication from the password server. */ + struct svma_state svma_state = { 0 }; + error_t (*verify_fn) (const char *password, + uid_t id, int is_group, + void *pwd_or_grp, void *hook) + = server_verify_make_auth; + void *verify_hook = &svma_state; + + /* Try to open the hurd password server. */ + svma_state.server = file_name_lookup (_SERVERS_PASSWORD, 0, 0); + + if (svma_state.server == MACH_PORT_NULL) + /* Can't open the password server, try to use our own authority in + the traditional unix manner. */ + { + verify_fn = 0; + verify_hook = 0; + } + + /* Check passwords. */ + err = ugids_verify (ugids, have_uids, have_gids, + getpass_fn, getpass_hook, verify_fn, verify_hook); + + if (! err) + /* The user apparently has access to all the ids, try to grant the + corresponding authentication. */ + if (verify_fn) + /* Merge the authentication we got from the password server into our + result. */ + { + if (num_from > 0) + /* Use FROM as well as the passwords to get authentication. */ + err = svma_state_add_auths (&svma_state, from, num_from); + + if (! err) + { + auth_t cur_auth = getauth (); + + err = + auth_makeauth (cur_auth, + svma_state.auths, MACH_MSG_TYPE_COPY_SEND, + svma_state.num_auths, + ugids->eff_uids.ids, ugids->eff_uids.num, + ugids->avail_uids.ids, ugids->avail_uids.num, + ugids->eff_gids.ids, ugids->eff_gids.num, + ugids->avail_gids.ids, ugids->avail_gids.num, + auth); + mach_port_deallocate (mach_task_self (), cur_auth); + + /* Avoid deallocating FROM when we clean up SVMA_STATE. */ + svma_state.num_auths -= num_from; + } + } + else + /* Try to authenticate the old fashioned way... */ + err = ugids_make_auth (ugids, from, num_from, auth); + + if (verify_fn) + /* Clean up any left over state. */ + { + int i; + + /* Get rid of auth ports. */ + for (i = 0; i < svma_state.num_auths; i++) + mach_port_deallocate (mach_task_self (), svma_state.auths[i]); + + /* Close password server. */ + mach_port_deallocate (mach_task_self (), svma_state.server); + + if (svma_state.num_auths > 0) + free (svma_state.auths); + } + + return err; +} |