summaryrefslogtreecommitdiffstats
path: root/usr.bin/sudo/auth
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/sudo/auth')
-rw-r--r--usr.bin/sudo/auth/API128
-rw-r--r--usr.bin/sudo/auth/afs.c98
-rw-r--r--usr.bin/sudo/auth/aix_auth.c75
-rw-r--r--usr.bin/sudo/auth/dce.c214
-rw-r--r--usr.bin/sudo/auth/fwtk.c156
-rw-r--r--usr.bin/sudo/auth/kerb4.c119
-rw-r--r--usr.bin/sudo/auth/kerb5.c312
-rw-r--r--usr.bin/sudo/auth/pam.c171
-rw-r--r--usr.bin/sudo/auth/passwd.c79
-rw-r--r--usr.bin/sudo/auth/rfc1938.c150
-rw-r--r--usr.bin/sudo/auth/secureware.c110
-rw-r--r--usr.bin/sudo/auth/securid.c111
-rw-r--r--usr.bin/sudo/auth/sia.c147
-rw-r--r--usr.bin/sudo/auth/sudo_auth.c243
-rw-r--r--usr.bin/sudo/auth/sudo_auth.h123
15 files changed, 2236 insertions, 0 deletions
diff --git a/usr.bin/sudo/auth/API b/usr.bin/sudo/auth/API
new file mode 100644
index 00000000000..4b336cc8c83
--- /dev/null
+++ b/usr.bin/sudo/auth/API
@@ -0,0 +1,128 @@
+NOTE: the Sudo auth API is subject to change
+
+Purpose: to provide a simple API for authentication methods that
+ encapsulates things nicely without turning into a maze
+ of #ifdef's
+
+The sudo_auth struct looks like this:
+
+typedef struct sudo_auth {
+ short flags; /* /* various flags, see below */
+ short status; /* status from verify routine */
+ char *name; /* name of the method in string form */
+ VOID *data; /* method-specific data pointer */
+
+ int (*init) __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+ int (*setup) __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+ int (*verify) __P((struct passwd *pw, char *p, sudo_auth *auth));
+ int (*cleanup) __P((struct passwd *pw, sudo_auth *auth));
+} sudo_auth;
+
+The variables in the struct are as follows:
+ flags Bitwise binary flags, see below.
+
+ status Contains the return value from the last run of
+ the "verify" function. Starts out as AUTH_FAILURE.
+
+ name The name of the authentication method as a C string.
+
+ data A pointer to method-specific data. This is passed to
+ all the functions of an auth method and is usually
+ initialized in the "init" or "setup" routines.
+
+Possible values of sudo_auth.flags:
+ FLAG_USER Whether or not the auth functions should run with
+ the euid of the invoking user instead of 0.
+
+ FLAG_CONFIGURED If set then the auth method is assumed to have been
+ configured successfully. All auth methods start out
+ with this set. If an "init" or "setup" function
+ fails, this bit is cleared.
+
+ FLAG_ONEANDONLY If set, this indicates that the method is the
+ only one in use. Can be used by auth functions
+ to determine whether to return a fatal or nonfatal
+ error.
+
+The member functions can return the following values:
+ AUTH_SUCCESS Function succeeded. For a ``verify'' function
+ this means the user correctly authenticated.
+
+ AUTH_FAILURE Function failed. If this is an ``init'' or
+ ``setup'' routine, the auth method will be
+ marked as !configured.
+
+ AUTH_FATAL A fatal error occurred. The routine should have
+ written an error message to stderr and optionally
+ sent mail to the administrator. (If log_error()
+ is called to do this, the NO_EXIT flag must be used.)
+ When verify_user() gets AUTH_FATAL from an auth
+ function it does an exit(1).
+
+The functions in the struct are as follows:
+
+ int init(struct passwd *pw, char **prompt, sudo_auth *auth)
+ Function to do any one-time initialization for the auth
+ method. All of the "init" functions are run before anything
+ else. A pointer to the prompt string may be used to add
+ method-specific info to the prompt.
+
+ int setup(struct passwd *pw, char **prompt, sudo_auth *auth)
+ Function to do method-specific setup. All the "setup"
+ routines are run before any of the "verify" routines. A
+ pointer to the prompt string may be used to add method-specific
+ info to the prompt.
+
+ int verify(struct passwd *pw, char *p, sudo_auth *auth)
+ Function to do user verification for this auth method. For
+ standalone auth methods ``p'' is the prompt string. For
+ normal auth methods, ``p'' is the password the user entered.
+ Note that standalone auth methods are responsible for
+ rerading the password themselves.
+
+ int cleanup(struct passwd *pw, sudo_auth *auth)
+ Function to do per-auth method cleanup. This is only run
+ at the end of the authentication process, after the user
+ has completely failed or succeeded to authenticate.
+ The ``auth->status'' variable contains the result of the
+ last authentication attempt which may be interesting.
+
+A note about standalone methods. Some authentication methods can't
+coexist with any others. This may be because they encapsulate other
+methods (pam, sia) or because they have a special way of interacting
+with the user (securid).
+
+Adding a new authentication method:
+
+Each method should live in its own file. Add prototypes for the functions
+in sudo_auth.h.
+
+If this is a standalone method, add it to the standalone #if cascade
+in sudo_auth.h. For instance, for a method, ``fooauth'', add:
+
+#elif defined(HAVE_FOOAUTH)
+# define AUTH_STANDALONE \
+ AUTH_ENTRY(0, "foo", \
+ foo_init, foo_setup, foo_verify, foo_cleanup)
+
+If the method needs to run as the user, not root, replace the first
+parameter to AUTH_ENTRY (0) with FLAG_USER. If you don't have a
+init/setup/cleanup routine, just use a NULL for that field.
+
+For a normal authentication method, add it to the ``auth_switch'' in
+sudo_auth.c. If ``fooauth'' is a normal auth method, its entry
+would look like:
+
+# ifdef HAVE_FOOAUTH
+ AUTH_ENTRY(0, "foo", foo_init, foo_setup, foo_verify, foo_cleanup)
+# endif
+
+Again, if the method doesn't need to run as root, replace the 0 with
+FLAG_USER. Likewise, if you don't have a init/setup/cleanup routine,
+just use a NULL for that field.
+
+NOTE: You should not make a method both ``standalone'' and
+ ``normal''. Just use the --without-passwd configure argument
+ to disable passwd/shadow file checking and then have your
+ auth routines check the FLAG_ONEANDONLY flag to see if
+ they are running standalone and act accordingly.
diff --git a/usr.bin/sudo/auth/afs.c b/usr.bin/sudo/auth/afs.c
new file mode 100644
index 00000000000..e9f6070ca4b
--- /dev/null
+++ b/usr.bin/sudo/auth/afs.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <afs/stds.h>
+#include <afs/kautils.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: afs.c,v 1.5 1999/08/14 15:36:45 millert Exp $";
+#endif /* lint */
+
+int
+afs_verify(pw, pass, auth)
+ struct passwd *pw;
+ char *pass;
+ sudo_auth *auth;
+{
+ struct ktc_encryptionKey afs_key;
+ struct ktc_token afs_token;
+
+ /* Try to just check the password */
+ ka_StringToKey(pass, NULL, &afs_key);
+ if (ka_GetAdminToken(pw->pw_name, /* name */
+ NULL, /* instance */
+ NULL, /* realm */
+ &afs_key, /* key (contains password) */
+ 0, /* lifetime */
+ &afs_token, /* token */
+ 0) == 0) /* new */
+ return(AUTH_SUCCESS);
+
+ /* Fall back on old method XXX - needed? */
+ setpag();
+ if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
+ pw->pw_name, /* name */
+ NULL, /* instance */
+ NULL, /* realm */
+ pass, /* password */
+ 0, /* lifetime */
+ NULL, /* expiration ptr (unused) */
+ 0, /* spare */
+ NULL) == 0) /* reason */
+ return(AUTH_SUCCESS);
+
+ return(AUTH_FAILURE);
+}
diff --git a/usr.bin/sudo/auth/aix_auth.c b/usr.bin/sudo/auth/aix_auth.c
new file mode 100644
index 00000000000..670c0fb6a7c
--- /dev/null
+++ b/usr.bin/sudo/auth/aix_auth.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: aix_auth.c,v 1.7 1999/10/07 21:21:07 millert Exp $";
+#endif /* lint */
+
+int
+aixauth_verify(pw, prompt, auth)
+ struct passwd *pw;
+ char *prompt;
+ sudo_auth *auth;
+{
+ char *message, *pass;
+ int reenter = 1;
+
+ pass = tgetpass(prompt, def_ival(I_PW_TIMEOUT) * 60, 1);
+ if (authenticate(pw->pw_name, pass, &reenter, &message) == 0)
+ return(AUTH_SUCCESS);
+ else
+ return(AUTH_FAILURE);
+}
diff --git a/usr.bin/sudo/auth/dce.c b/usr.bin/sudo/auth/dce.c
new file mode 100644
index 00000000000..012467b4836
--- /dev/null
+++ b/usr.bin/sudo/auth/dce.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 1996, 1998, 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed by Jeff Earickson
+ * of Colby College, Waterville, ME <jaearick@colby.edu>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * The code below basically comes from the examples supplied on
+ * the OSF DCE 1.0.3 manpages for the sec_login routines, with
+ * enough additional polishing to make the routine work with the
+ * rest of sudo.
+ *
+ * This code is known to work on HP 700 and 800 series systems
+ * running HP-UX 9.X and 10.X, with either HP's version 1.2.1 of DCE.
+ * (aka, OSF DCE 1.0.3) or with HP's version 1.4 of DCE (aka, OSF
+ * DCE 1.1).
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <dce/rpc.h>
+#include <dce/sec_login.h>
+#include <dce/dce_error.h> /* required to call dce_error_inq_text routine */
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: dce.c,v 1.7 1999/08/31 09:39:17 millert Exp $";
+#endif /* lint */
+
+static int check_dce_status __P((error_status_t, char *));
+
+int
+dce_verify(pw, plain_pw, auth)
+ struct passwd *pw;
+ char *plain_pw;
+ sudo_auth *auth;
+{
+ struct passwd temp_pw;
+ sec_passwd_rec_t password_rec;
+ sec_login_handle_t login_context;
+ boolean32 reset_passwd;
+ sec_login_auth_src_t auth_src;
+ error_status_t status;
+
+ /*
+ * Create the local context of the DCE principal necessary
+ * to perform authenticated network operations. The network
+ * identity set up by this operation cannot be used until it
+ * is validated via sec_login_validate_identity().
+ */
+ if (sec_login_setup_identity((unsigned_char_p_t) pw->pw_name,
+ sec_login_no_flags, &login_context, &status)) {
+
+ if (check_dce_status(status, "sec_login_setup_identity(1):"))
+ return(AUTH_FAILURE);
+
+ password_rec.key.key_type = sec_passwd_plain;
+ password_rec.key.tagged_union.plain = (idl_char *) plain_pw;
+ password_rec.pepper = NULL;
+ password_rec.version_number = sec_passwd_c_version_none;
+
+ /* Validate the login context with the password */
+ if (sec_login_validate_identity(login_context, &password_rec,
+ &reset_passwd, &auth_src, &status)) {
+
+ if (check_dce_status(status, "sec_login_validate_identity(1):"))
+ return(AUTH_FAILURE);
+
+ /*
+ * Certify that the DCE Security Server used to set
+ * up and validate a login context is legitimate. Makes
+ * sure that we didn't get spoofed by another DCE server.
+ */
+ if (!sec_login_certify_identity(login_context, &status)) {
+ (void) fprintf(stderr, "Whoa! Bogus authentication server!\n");
+ (void) check_dce_status(status,"sec_login_certify_identity(1):");
+ return(AUTH_FAILURE);
+ }
+ if (check_dce_status(status, "sec_login_certify_identity(2):"))
+ return(AUTH_FAILURE);
+
+ /*
+ * Sets the network credentials to those specified
+ * by the now validated login context.
+ */
+ sec_login_set_context(login_context, &status);
+ if (check_dce_status(status, "sec_login_set_context:"))
+ return(AUTH_FAILURE);
+
+ /*
+ * Oops, your credentials were no good. Possibly
+ * caused by clock times out of adjustment between
+ * DCE client and DCE security server...
+ */
+ if (auth_src != sec_login_auth_src_network) {
+ (void) fprintf(stderr,
+ "You have no network credentials.\n");
+ return(AUTH_FAILURE);
+ }
+ /* Check if the password has aged and is thus no good */
+ if (reset_passwd) {
+ (void) fprintf(stderr,
+ "Your DCE password needs resetting.\n");
+ return(AUTH_FAILURE);
+ }
+
+ /*
+ * We should be a valid user by this point. Pull the
+ * user's password structure from the DCE security
+ * server just to make sure. If we get it with no
+ * problems, then we really are legitimate...
+ */
+ sec_login_get_pwent(login_context, (sec_login_passwd_t) &temp_pw,
+ &status);
+ if (check_dce_status(status, "sec_login_get_pwent:"))
+ return(AUTH_FAILURE);
+
+ /*
+ * If we get to here, then the pwent above properly fetched
+ * the password structure from the DCE registry, so the user
+ * must be valid. We don't really care what the user's
+ * registry password is, just that the user could be
+ * validated. In fact, if we tried to compare the local
+ * password to the DCE entry at this point, the operation
+ * would fail if the hidden password feature is turned on,
+ * because the password field would contain an asterisk.
+ * Also go ahead and destroy the user's DCE login context
+ * before we leave here (and don't bother checking the
+ * status), in order to clean up credentials files in
+ * /opt/dcelocal/var/security/creds. By doing this, we are
+ * assuming that the user will not need DCE authentication
+ * later in the program, only local authentication. If this
+ * is not true, then the login_context will have to be
+ * returned to the calling program, and the context purged
+ * somewhere later in the program.
+ */
+ sec_login_purge_context(&login_context, &status);
+ return(AUTH_SUCCESS);
+ } else {
+ if(check_dce_status(status, "sec_login_validate_identity(2):"))
+ return(AUTH_FAILURE);
+ sec_login_purge_context(&login_context, &status);
+ if(check_dce_status(status, "sec_login_purge_context:"))
+ return(AUTH_FAILURE);
+ }
+ }
+ (void) check_dce_status(status, "sec_login_setup_identity(2):");
+ return(AUTH_FAILURE);
+}
+
+/* Returns 0 for DCE "ok" status, 1 otherwise */
+static int
+check_dce_status(input_status, comment)
+ error_status_t input_status;
+ char *comment;
+{
+ int error_stat;
+ unsigned char error_string[dce_c_error_string_len];
+
+ if (input_status == rpc_s_ok)
+ return(0);
+ dce_error_inq_text(input_status, error_string, &error_stat);
+ (void) fprintf(stderr, "%s %s\n", comment, error_string);
+ return(1);
+}
diff --git a/usr.bin/sudo/auth/fwtk.c b/usr.bin/sudo/auth/fwtk.c
new file mode 100644
index 00000000000..448faf87f97
--- /dev/null
+++ b/usr.bin/sudo/auth/fwtk.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <auth.h>
+#include <firewall.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: fwtk.c,v 1.9 1999/10/12 00:53:41 millert Exp $";
+#endif /* lint */
+
+int
+fwtk_init(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+ static Cfg *confp; /* Configuration entry struct */
+ char resp[128]; /* Response from the server */
+
+ if ((confp = cfg_read("sudo")) == (Cfg *)-1) {
+ (void) fprintf(stderr, "%s: cannot read fwtk config.\n", Argv[0]);
+ return(AUTH_FATAL);
+ }
+
+ if (auth_open(confp)) {
+ (void) fprintf(stderr, "%s: cannot connect to authentication server.\n",
+ Argv[0]);
+ return(AUTH_FATAL);
+ }
+
+ /* Get welcome message from auth server */
+ if (auth_recv(resp, sizeof(resp))) {
+ (void) fprintf(stderr,
+ "%s: lost connection to authentication server.\n", Argv[0]);
+ return(AUTH_FATAL);
+ }
+ if (strncmp(resp, "Authsrv ready", 13) != 0) {
+ (void) fprintf(stderr,
+ "%s: authentication server error.\n%s\n", Argv[0], resp);
+ return(AUTH_FATAL);
+ }
+
+ return(AUTH_SUCCESS);
+}
+
+int
+fwtk_verify(pw, prompt, auth)
+ struct passwd *pw;
+ char *prompt;
+ sudo_auth *auth;
+{
+ char *pass; /* Password from the user */
+ char buf[SUDO_PASS_MAX + 12]; /* General prupose buffer */
+ char resp[128]; /* Response from the server */
+ extern int nil_pw;
+
+ /* Send username to authentication server. */
+ (void) snprintf(buf, sizeof(buf), "authorize %s 'sudo'", pw->pw_name);
+ if (auth_send(buf) || auth_recv(resp, sizeof(resp))) {
+ (void) fprintf(stderr,
+ "%s: lost connection to authentication server.\n", Argv[0]);
+ return(AUTH_FATAL);
+ }
+
+ /* Get the password/response from the user. */
+ if (strncmp(resp, "challenge ", 10) == 0) {
+ (void) snprintf(buf, sizeof(buf), "%s\nResponse: ", &resp[10]);
+ pass = tgetpass(buf, def_ival(I_PW_TIMEOUT) * 60, 0);
+ } else if (strncmp(resp, "password", 8) == 0) {
+ pass = tgetpass(prompt, def_ival(I_PW_TIMEOUT) * 60, 1);
+ } else {
+ (void) fprintf(stderr, "%s: %s\n", Argv[0], resp);
+ return(AUTH_FATAL);
+ }
+ if (!pass || *pass == '\0')
+ nil_pw = 1; /* empty password */
+
+ /* Send the user's response to the server */
+ (void) snprintf(buf, sizeof(buf), "response '%s'", pass);
+ if (auth_send(buf) || auth_recv(resp, sizeof(resp))) {
+ (void) fprintf(stderr,
+ "%s: lost connection to authentication server.\n", Argv[0]);
+ return(AUTH_FATAL);
+ }
+
+ if (strncmp(resp, "ok", 2) == 0)
+ return(AUTH_SUCCESS);
+
+ /* Main loop prints "Permission Denied" or insult. */
+ if (strcmp(resp, "Permission Denied.") != 0)
+ fprintf(stderr, "%s: %s\n", Argv[0], resp);
+ return(AUTH_FAILURE);
+}
+
+int
+fwtk_cleanup(pw, auth)
+ struct passwd *pw;
+ sudo_auth *auth;
+{
+
+ auth_close();
+ return(AUTH_SUCCESS);
+}
diff --git a/usr.bin/sudo/auth/kerb4.c b/usr.bin/sudo/auth/kerb4.c
new file mode 100644
index 00000000000..2791ec9aef5
--- /dev/null
+++ b/usr.bin/sudo/auth/kerb4.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <krb.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: kerb4.c,v 1.5 1999/08/14 15:36:46 millert Exp $";
+#endif /* lint */
+
+int
+kerb4_init(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+ static char realm[REALM_SZ];
+
+ /* Don't try to verify root */
+ if (pw->pw_uid == 0)
+ return(AUTH_FAILURE);
+
+ /* Get the local realm, or retrun failure (no krb.conf) */
+ if (krb_get_lrealm(realm, 1) != KSUCCESS)
+ return(AUTH_FAILURE);
+
+ /* Stash a pointer to the realm (used in kerb4_verify) */
+ auth->data = (VOID *) realm;
+
+ return(AUTH_SUCCESS);
+}
+
+int
+kerb4_verify(pw, pass, auth)
+ struct passwd *pw;
+ char *pass;
+ sudo_auth *auth;
+{
+ char tkfile[sizeof(_PATH_SUDO_TIMEDIR) + 4 + MAX_UID_T_LEN];
+ char *realm = (char *) auth->data;
+ int error;
+
+ /*
+ * Set the ticket file to be in sudo sudo timedir so we don't
+ * wipe out other (real) kerberos tickets.
+ */
+ (void) sprintf(tkfile, "%s/tkt%ld", _PATH_SUDO_TIMEDIR, (long) pw->pw_uid);
+ (void) krb_set_tkt_string(tkfile);
+
+ /* Convert the password to a ticket given. */
+ error = krb_get_pw_in_tkt(pw->pw_name, "", realm, "krbtgt", realm,
+ DEFAULT_TKT_LIFE, pass);
+
+ switch (error) {
+ case INTK_OK:
+ dest_tkt(); /* we are done with the temp ticket */
+ return(AUTH_SUCCESS);
+ break;
+ case INTK_BADPW:
+ case KDC_PR_UNKNOWN:
+ break;
+ default:
+ (void) fprintf(stderr, "Warning: Kerberos error: %s\n",
+ krb_err_txt[error]);
+ }
+
+ return(AUTH_FAILURE);
+}
diff --git a/usr.bin/sudo/auth/kerb5.c b/usr.bin/sudo/auth/kerb5.c
new file mode 100644
index 00000000000..f9adb3dcaea
--- /dev/null
+++ b/usr.bin/sudo/auth/kerb5.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed by Frank Cusack
+ * <fcusack@fcusack.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <krb5.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: kerb5.c,v 1.10 1999/10/13 02:34:55 millert Exp $";
+#endif /* lint */
+
+static int verify_krb_v5_tgt __P((krb5_context, krb5_ccache, char *));
+static struct _sudo_krb5_data {
+ krb5_context sudo_context;
+ krb5_principal princ;
+ krb5_ccache ccache;
+} sudo_krb5_data = { NULL, NULL, NULL };
+typedef struct _sudo_krb5_data *sudo_krb5_datap;
+
+extern krb5_cc_ops krb5_mcc_ops;
+
+int
+kerb5_init(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+ krb5_context sudo_context;
+ krb5_ccache ccache;
+ krb5_principal princ;
+ krb5_error_code error;
+ char cache_name[64];
+ char *pname;
+
+ auth->data = (VOID *) &sudo_krb5_data; /* Stash all our data here */
+
+ if (error = krb5_init_context(&(sudo_krb5_data.sudo_context))) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to initialize context: %s", auth->name,
+ error_message(error));
+ return(AUTH_FAILURE);
+ }
+ sudo_context = sudo_krb5_data.sudo_context;
+
+ if (error = krb5_parse_name(sudo_context, pw->pw_name,
+ &(sudo_krb5_data.princ))) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to parse '%s': %s", auth->name, pw->pw_name,
+ error_message(error));
+ return(AUTH_FAILURE);
+ }
+ princ = sudo_krb5_data.princ;
+
+ /*
+ * Really, we need to tell the caller not to prompt for password.
+ * The API does not currently provide this unless the auth is standalone.
+ */
+#if 1
+ if (error = krb5_unparse_name(sudo_context, princ, &pname)) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to unparse princ ('%s'): %s", auth->name,
+ pw->pw_name, error_message(error));
+ return(AUTH_FAILURE);
+ }
+
+ /* Only rewrite prompt if user didn't specify their own. */
+ /*if (!strcmp(prompt, PASSPROMPT)) { */
+ easprintf(promptp, "Password for %s: ", pname);
+ /*}*/
+ free(pname);
+#endif
+
+ /* For CNS compatibility */
+ if (error = krb5_cc_register(sudo_context, &krb5_mcc_ops, FALSE)) {
+ if (error != KRB5_CC_TYPE_EXISTS) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to use Memory ccache: %s", auth->name,
+ error_message(error));
+ return(AUTH_FAILURE);
+ }
+ }
+
+ (void) snprintf(cache_name, sizeof(cache_name), "MEMORY:sudocc_%ld",
+ (long) getpid());
+ if (error = krb5_cc_resolve(sudo_context, cache_name,
+ &(sudo_krb5_data.ccache))) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to resolve ccache: %s", auth->name,
+ error_message(error));
+ return(AUTH_FAILURE);
+ }
+ ccache = sudo_krb5_data.ccache;
+
+ if (error = krb5_cc_initialize(sudo_context, ccache, princ)) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to initialize ccache: %s", auth->name,
+ error_message(error));
+ return(AUTH_FAILURE);
+ }
+
+ return(AUTH_SUCCESS);
+}
+
+int
+kerb5_verify(pw, pass, auth)
+ struct passwd *pw;
+ char *pass;
+ sudo_auth *auth;
+{
+ krb5_context sudo_context;
+ krb5_principal princ;
+ krb5_ccache ccache;
+ krb5_creds creds;
+ krb5_error_code error;
+ krb5_get_init_creds_opt opts;
+ char cache_name[64];
+
+ sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
+ princ = ((sudo_krb5_datap) auth->data)->princ;
+ ccache = ((sudo_krb5_datap) auth->data)->ccache;
+
+ /* Initialize options to defaults */
+ krb5_get_init_creds_opt_init(&opts);
+
+ /* Note that we always obtain a new TGT to verify the user */
+ if (error = krb5_get_init_creds_password(sudo_context, &creds, princ,
+ pass, krb5_prompter_posix,
+ NULL, 0, NULL, &opts)) {
+ if (error == KRB5KRB_AP_ERR_BAD_INTEGRITY) /* Bad password */
+ return(AUTH_FAILURE);
+ /* Some other error */
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to get credentials: %s", auth->name,
+ error_message(error));
+ return(AUTH_FAILURE);
+ }
+
+ /* Stash the TGT so we can verify it. */
+ if (error = krb5_cc_store_cred(sudo_context, ccache, &creds)) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to store credentials: %s", auth->name,
+ error_message(error));
+ } else {
+ error = verify_krb_v5_tgt(sudo_context, ccache, auth->name);
+ }
+
+ krb5_free_cred_contents(sudo_context, &creds);
+ return (error ? AUTH_FAILURE : AUTH_SUCCESS);
+}
+
+int
+kerb5_cleanup(pw, auth)
+ struct passwd *pw;
+ sudo_auth *auth;
+{
+ krb5_context sudo_context;
+ krb5_principal princ;
+ krb5_ccache ccache;
+
+ sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
+ princ = ((sudo_krb5_datap) auth->data)->princ;
+ ccache = ((sudo_krb5_datap) auth->data)->ccache;
+
+ if (sudo_context) {
+ if (ccache)
+ krb5_cc_destroy(sudo_context, ccache);
+ if (princ)
+ krb5_free_principal(sudo_context, princ);
+ krb5_free_context(sudo_context);
+ }
+
+ return(AUTH_SUCCESS);
+}
+
+/*
+ * This routine with some modification is from the MIT V5B6 appl/bsd/login.c
+ *
+ * Verify the Kerberos ticket-granting ticket just retrieved for the
+ * user. If the Kerberos server doesn't respond, assume the user is
+ * trying to fake us out (since we DID just get a TGT from what is
+ * supposedly our KDC). If the host/<host> service is unknown (i.e.,
+ * the local keytab doesn't have it), return success but log the error.
+ *
+ * This needs to run as root (to read the host service ticket).
+ *
+ * Returns 0 for successful authentication, non-zero for failure.
+ */
+static int
+verify_krb_v5_tgt(sudo_context, ccache, auth_name)
+ krb5_context sudo_context;
+ krb5_ccache ccache;
+ char *auth_name; /* For error reporting */
+{
+ char phost[BUFSIZ];
+ krb5_error_code error;
+ krb5_principal princ;
+ krb5_data packet;
+ krb5_keyblock *keyblock = 0;
+ krb5_auth_context auth_context = NULL;
+
+ packet.data = 0;
+
+ /*
+ * Get the server principal for the local host.
+ * (Use defaults of "host" and canonicalized local name.)
+ */
+ if (error = krb5_sname_to_principal(sudo_context, NULL, NULL,
+ KRB5_NT_SRV_HST, &princ)) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to get host principal: %s", auth_name,
+ error_message(error));
+ return(-1);
+ }
+
+ /* Extract the name directly. Yow. */
+ strncpy(phost, krb5_princ_component(sudo_context, princ, 1)->data,
+ sizeof(phost) - 1);
+ phost[sizeof(phost) - 1] = '\0';
+
+ /*
+ * Do we have host/<host> keys?
+ * (use default keytab, kvno IGNORE_VNO to get the first match,
+ * and enctype is currently ignored anyhow.)
+ */
+ if (error = krb5_kt_read_service_key(sudo_context, NULL, princ, 0,
+ ENCTYPE_DES_CBC_MD5, &keyblock)) {
+ /* Keytab or service key does not exist. */
+ log_error(NO_EXIT,
+ "%s: host service key not found: %s", auth_name,
+ error_message(error));
+ error = 0;
+ goto cleanup;
+ }
+ if (keyblock)
+ krb5_free_keyblock(sudo_context, keyblock);
+
+ /* Talk to the kdc and construct the ticket. */
+ error = krb5_mk_req(sudo_context, &auth_context, 0, "host", phost,
+ NULL, ccache, &packet);
+ if (auth_context) {
+ krb5_auth_con_free(sudo_context, auth_context);
+ auth_context = NULL; /* setup for rd_req */
+ }
+
+ /* Try to use the ticket. */
+ if (!error)
+ error = krb5_rd_req(sudo_context, &auth_context, &packet, princ,
+ NULL, NULL, NULL);
+cleanup:
+ if (packet.data)
+ krb5_free_data_contents(sudo_context, &packet);
+ krb5_free_principal(sudo_context, princ);
+
+ if (error)
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: Cannot verify TGT! Possible attack!: %s", auth_name,
+ error_message(error));
+ return(error);
+}
diff --git a/usr.bin/sudo/auth/pam.c b/usr.bin/sudo/auth/pam.c
new file mode 100644
index 00000000000..623dcab742d
--- /dev/null
+++ b/usr.bin/sudo/auth/pam.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <security/pam_appl.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: pam.c,v 1.10 1999/10/07 21:21:07 millert Exp $";
+#endif /* lint */
+
+static int sudo_conv __P((int, PAM_CONST struct pam_message **,
+ struct pam_response **, VOID *));
+static char *def_prompt;
+
+int
+pam_init(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+ static struct pam_conv pam_conv;
+ pam_handle_t *pamh;
+
+ /* Initial PAM setup */
+ pam_conv.conv = sudo_conv;
+ if (pam_start("sudo", pw->pw_name, &pam_conv, &pamh) != PAM_SUCCESS) {
+ log_error(USE_ERRNO|NO_EXIT|NO_MAIL,
+ "unable to initialize PAM");
+ return(AUTH_FATAL);
+ }
+ auth->data = (VOID *) pamh;
+ return(AUTH_SUCCESS);
+}
+
+int
+pam_verify(pw, prompt, auth)
+ struct passwd *pw;
+ char *prompt;
+ sudo_auth *auth;
+{
+ pam_handle_t *pamh = (pam_handle_t *) auth->data;
+
+ def_prompt = prompt; /* for sudo_conv */
+
+ /* PAM_SILENT prevents error messages from going to syslog(3) */
+ if (pam_authenticate(pamh, PAM_SILENT) == PAM_SUCCESS)
+ return(AUTH_SUCCESS);
+ else
+ return(AUTH_FAILURE);
+}
+
+int
+pam_cleanup(pw, auth)
+ struct passwd *pw;
+ sudo_auth *auth;
+{
+ pam_handle_t *pamh = (pam_handle_t *) auth->data;
+
+ if (pam_end(pamh, (auth->status == AUTH_SUCCESS)) == PAM_SUCCESS)
+ return(AUTH_SUCCESS);
+ else
+ return(AUTH_FAILURE);
+}
+
+/*
+ * ``Conversation function'' for PAM.
+ */
+static int
+sudo_conv(num_msg, msg, response, appdata_ptr)
+ int num_msg;
+ PAM_CONST struct pam_message **msg;
+ struct pam_response **response;
+ VOID *appdata_ptr;
+{
+ struct pam_response *pr;
+ struct pam_message *pm;
+ char *p = def_prompt;
+ int echo = 0;
+ extern int nil_pw;
+
+ if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL)
+ return(PAM_CONV_ERR);
+ (void) memset((VOID *)*response, 0, num_msg * sizeof(struct pam_response));
+
+ for (pr = *response, pm = *msg; num_msg--; pr++, pm++) {
+ switch (pm->msg_style) {
+ case PAM_PROMPT_ECHO_ON:
+ echo = 1;
+ case PAM_PROMPT_ECHO_OFF:
+ /* Override default prompt for unix auth */
+ if (strcmp(p, "Password: ") && strcmp(p, "Password:"))
+ p = (char *) pm->msg;
+ pr->resp = estrdup((char *) tgetpass(p,
+ def_ival(I_PW_TIMEOUT) * 60, !echo));
+ if (*pr->resp == '\0')
+ nil_pw = 1; /* empty password */
+ break;
+ case PAM_TEXT_INFO:
+ if (pm->msg)
+ (void) puts(pm->msg);
+ break;
+ case PAM_ERROR_MSG:
+ if (pm->msg) {
+ (void) fputs(pm->msg, stderr);
+ (void) fputc('\n', stderr);
+ }
+ break;
+ default:
+ /* Something odd happened */
+ /* XXX - should free non-NULL response members */
+ free(*response);
+ *response = NULL;
+ return(PAM_CONV_ERR);
+ break;
+ }
+ }
+
+ return(PAM_SUCCESS);
+}
diff --git a/usr.bin/sudo/auth/passwd.c b/usr.bin/sudo/auth/passwd.c
new file mode 100644
index 00000000000..62f3a126584
--- /dev/null
+++ b/usr.bin/sudo/auth/passwd.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: passwd.c,v 1.4 1999/08/14 15:36:46 millert Exp $";
+#endif /* lint */
+
+int
+passwd_verify(pw, pass, auth)
+ struct passwd *pw;
+ char *pass;
+ sudo_auth *auth;
+{
+
+#ifdef HAVE_GETAUTHUID
+ /* Ultrix shadow passwords may use crypt16() */
+ if (!strcmp(pw->pw_passwd, (char *) crypt16(pass, pw->pw_passwd)))
+ return(AUTH_SUCCESS);
+#endif /* HAVE_GETAUTHUID */
+
+ /* Normal UN*X password check */
+ if (!strcmp(pw->pw_passwd, (char *) crypt(pass, pw->pw_passwd)))
+ return(AUTH_SUCCESS);
+
+ return(AUTH_FAILURE);
+}
diff --git a/usr.bin/sudo/auth/rfc1938.c b/usr.bin/sudo/auth/rfc1938.c
new file mode 100644
index 00000000000..bad20d24dca
--- /dev/null
+++ b/usr.bin/sudo/auth/rfc1938.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1994-1996,1998-1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#if defined(HAVE_SKEY)
+#include <skey.h>
+#define RFC1938 skey
+#define rfc1938challenge skeychallenge
+#define rfc1938verify skeyverify
+#elif defined(HAVE_OPIE)
+#include <opie.h>
+#define RFC1938 opie
+#define rfc1938challenge opiechallenge
+#define rfc1938verify opieverify
+#endif
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: rfc1938.c,v 1.8 1999/10/07 21:21:07 millert Exp $";
+#endif /* lint */
+
+int
+rfc1938_setup(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+ char challenge[256];
+ static char *orig_prompt = NULL, *new_prompt = NULL;
+ static int op_len, np_size;
+ static struct RFC1938 rfc1938;
+
+ /* Stash a pointer to the rfc1938 struct if we have not initialized */
+ if (!auth->data)
+ auth->data = &rfc1938;
+
+ /* Save the original prompt */
+ if (orig_prompt == NULL) {
+ orig_prompt = *promptp;
+ op_len = strlen(orig_prompt);
+
+ /* Ignore trailing colon (we will add our own) */
+ if (orig_prompt[op_len - 1] == ':')
+ op_len--;
+ else if (op_len >= 2 && orig_prompt[op_len - 1] == ' '
+ && orig_prompt[op_len - 2] == ':')
+ op_len -= 2;
+ }
+
+#ifdef HAVE_SKEY
+ /* Close old stream */
+ if (rfc1938.keyfile)
+ (void) fclose(rfc1938.keyfile);
+#endif
+
+ /*
+ * Look up the user and get the rfc1938 challenge.
+ * If the user is not in the OTP db, only post a fatal error if
+ * we are running alone (since they may just use a normal passwd).
+ */
+ if (rfc1938challenge(&rfc1938, pw->pw_name, challenge) != 0) {
+ if (IS_ONEANDONLY(auth)) {
+ (void) fprintf(stderr,
+ "%s: You do not exist in the %s database.\n",
+ Argv[0], auth->name);
+ return(AUTH_FATAL);
+ } else {
+ return(AUTH_FAILURE);
+ }
+ }
+
+ /* Get space for new prompt with embedded challenge */
+ if (np_size < op_len + strlen(challenge) + 7) {
+ np_size = op_len + strlen(challenge) + 7;
+ new_prompt = (char *) erealloc(new_prompt, np_size);
+ }
+
+ if (def_flag(I_LONG_OTP_PROMPT))
+ (void) sprintf(new_prompt, "%s\n%s", challenge, orig_prompt);
+ else
+ (void) sprintf(new_prompt, "%.*s [ %s ]:", op_len, orig_prompt,
+ challenge);
+
+ *promptp = new_prompt;
+ return(AUTH_SUCCESS);
+}
+
+int
+rfc1938_verify(pw, pass, auth)
+ struct passwd *pw;
+ char *pass;
+ sudo_auth *auth;
+{
+
+ if (rfc1938verify((struct RFC1938 *) auth->data, pass) == 0)
+ return(AUTH_SUCCESS);
+ else
+ return(AUTH_FAILURE);
+}
diff --git a/usr.bin/sudo/auth/secureware.c b/usr.bin/sudo/auth/secureware.c
new file mode 100644
index 00000000000..ddba29fbc9b
--- /dev/null
+++ b/usr.bin/sudo/auth/secureware.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1998, 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+#ifdef __hpux
+# undef MAXINT
+# include <hpsecurity.h>
+#else
+# include <sys/security.h>
+#endif /* __hpux */
+#include <prot.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: secureware.c,v 1.7 1999/08/22 09:59:28 millert Exp $";
+#endif /* lint */
+
+int
+secureware_init(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+#ifdef __alpha
+ extern int crypt_type;
+
+ if (crypt_type == INT_MAX)
+ return(AUTH_FAILURE); /* no shadow */
+#endif
+ return(AUTH_SUCCESS);
+}
+
+int
+secureware_verify(pw, pass, auth)
+ struct passwd *pw;
+ char *pass;
+ sudo_auth *auth;
+{
+#ifdef __alpha
+ extern int crypt_type;
+
+# ifdef HAVE_DISPCRYPT
+ if (strcmp(user_passwd, dispcrypt(pass, user_passwd, crypt_type)) == 0)
+ return(AUTH_SUCCESS);
+# else
+ if (crypt_type == AUTH_CRYPT_BIGCRYPT) {
+ if (strcmp(user_passwd, bigcrypt(pass, user_passwd)) == 0)
+ return(AUTH_SUCCESS);
+ } else if (crypt_type == AUTH_CRYPT_CRYPT16) {
+ if (strcmp(user_passwd, crypt(pass, user_passwd)) == 0)
+ return(AUTH_SUCCESS);
+ }
+# endif /* HAVE_DISPCRYPT */
+#elif defined(HAVE_BIGCRYPT)
+ if (strcmp(user_passwd, bigcrypt(pass, user_passwd)) == 0)
+ return(AUTH_SUCCESS);
+#endif /* __alpha */
+
+ return(AUTH_FAILURE);
+}
diff --git a/usr.bin/sudo/auth/securid.c b/usr.bin/sudo/auth/securid.c
new file mode 100644
index 00000000000..dff22632cca
--- /dev/null
+++ b/usr.bin/sudo/auth/securid.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed by Giles Todd
+ * <giles@gt.demon.co.uk>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <sdi_athd.h>
+#include <sdconf.h>
+#include <sdacmvls.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: securid.c,v 1.5 1999/08/14 15:36:46 millert Exp $";
+#endif /* lint */
+
+union config_record configure;
+
+int
+securid_init(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+
+ creadcfg(); /* Only read config file once */
+ return(AUTH_SUCCESS);
+}
+
+int
+securid_setup(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+ static SD_CLIENT sd_dat; /* SecurID data block */
+
+ /* Re-initialize SecurID every time. */
+ auth->data = (VOID *) &sd_dat;
+ if (sd_init(sd) == 0)
+ return(AUTH_SUCCESS);
+ else {
+ (void) fprintf(stderr, "%s: Cannot contact SecurID server\n", Argv[0]);
+ return(AUTH_FATAL);
+ }
+}
+
+int
+securid_verify(pw, pass, auth)
+ struct passwd *pw;
+ char *pass;
+ sudo_auth *auth;
+{
+ struct SD_CLIENT *sd = (struct SD_CLIENT *) auth->data;
+
+ if (sd_auth(sd) == ACM_OK)
+ return(AUTH_SUCCESS);
+ else
+ return(AUTH_FAILURE);
+}
diff --git a/usr.bin/sudo/auth/sia.c b/usr.bin/sudo/auth/sia.c
new file mode 100644
index 00000000000..d41263c9603
--- /dev/null
+++ b/usr.bin/sudo/auth/sia.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed by Spider Boardman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <siad.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: sia.c,v 1.8 1999/10/07 21:21:07 millert Exp $";
+#endif /* lint */
+
+static int sudo_collect __P((int, int, uchar_t *, int, prompt_t *));
+
+static char *def_prompt;
+
+/*
+ * Collection routine (callback) for limiting the timeouts in SIA
+ * prompts and (possibly) setting a custom prompt.
+ */
+static int
+sudo_collect(timeout, rendition, title, nprompts, prompts)
+ int timeout;
+ int rendition;
+ uchar_t *title;
+ int nprompts;
+ prompt_t *prompts;
+{
+ switch (rendition) {
+ case SIAFORM:
+ case SIAONELINER:
+ if (timeout <= 0 || timeout > def_ival(I_PW_TIMEOUT) * 60)
+ timeout = def_ival(I_PW_TIMEOUT) * 60;
+ /*
+ * Substitute custom prompt if a) the sudo prompt is not "Password:"
+ * and b) the SIA prompt is "Password:" (so we know it is safe).
+ * This keeps us from overwriting things like S/Key challenges.
+ */
+ if (strcmp((char *)prompts[0].prompt, "Password:") == 0 &&
+ strcmp(def_prompt, "Password:") != 0)
+ prompts[0].prompt = (unsigned char *)def_prompt;
+ break;
+ default:
+ break;
+ }
+
+ return sia_collect_trm(timeout, rendition, title, nprompts, prompts);
+}
+
+int
+sia_setup(pw, promptp, auth)
+ struct passwd *pw;
+ char **promptp;
+ sudo_auth *auth;
+{
+ SIAENTITY *siah = NULL;
+
+ if (sia_ses_init(&siah, Argc, Argv, NULL, pw->pw_name, ttyname(0), 1, NULL)
+ != SIASUCCESS) {
+
+ log_error(USE_ERRNO|NO_EXIT|NO_MAIL,
+ "unable to initialize SIA session");
+ return(AUTH_FATAL);
+ }
+
+ auth->data = (VOID *) siah;
+ return(AUTH_SUCCESS);
+}
+
+int
+sia_verify(pw, prompt, auth)
+ struct passwd *pw;
+ char *prompt;
+ sudo_auth *auth;
+{
+ SIAENTITY *siah = (SIAENTITY *) auth->data;
+
+ def_prompt = prompt; /* for sudo_collect */
+
+ /* XXX - need a way to detect user hitting return or EOF at prompt */
+ if (sia_ses_reauthent(sudo_collect, siah) == SIASUCCESS)
+ return(AUTH_SUCCESS);
+ else
+ return(AUTH_FAILURE);
+}
+
+int
+sia_cleanup(pw, auth)
+ struct passwd *pw;
+ sudo_auth *auth;
+{
+ SIAENTITY *siah = (SIAENTITY *) auth->data;
+
+ (void) sia_ses_release(&siah);
+ return(AUTH_SUCCESS);
+}
diff --git a/usr.bin/sudo/auth/sudo_auth.c b/usr.bin/sudo/auth/sudo_auth.c
new file mode 100644
index 00000000000..74a20ce509b
--- /dev/null
+++ b/usr.bin/sudo/auth/sudo_auth.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <time.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+#include "insults.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo: sudo_auth.c,v 1.15 1999/10/13 02:34:55 millert Exp $";
+#endif /* lint */
+
+sudo_auth auth_switch[] = {
+#ifdef AUTH_STANDALONE
+ AUTH_STANDALONE
+#else
+# ifndef WITHOUT_PASSWD
+ AUTH_ENTRY(0, "passwd", NULL, NULL, passwd_verify, NULL)
+# endif
+# if defined(HAVE_SECUREWARE) && !defined(WITHOUT_PASSWD)
+ AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL)
+# endif
+# ifdef HAVE_AFS
+ AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL)
+# endif
+# ifdef HAVE_DCE
+ AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL)
+# endif
+# ifdef HAVE_KERB4
+ AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
+# endif
+# ifdef HAVE_KERB5
+ AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup)
+# endif
+# ifdef HAVE_SKEY
+ AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
+# endif
+# ifdef HAVE_OPIE
+ AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL)
+# endif
+#endif /* AUTH_STANDALONE */
+ AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
+};
+
+int nil_pw; /* I hate resorting to globals like this... */
+
+void
+verify_user(prompt)
+ char *prompt;
+{
+ short counter = def_ival(I_PW_TRIES) + 1;
+ short success = AUTH_FAILURE;
+ short status;
+ char *p;
+ sudo_auth *auth;
+
+ /* Make sure we have at least one auth method. */
+ if (auth_switch[0].name == NULL)
+ log_error(0, "%s %s %s",
+ "There are no authentication methods compiled into sudo!",
+ "If you want to turn off authentication, use the",
+ "--disable-authentication configure option.");
+
+ /* Set FLAG_ONEANDONLY if there is only one auth method. */
+ if (auth_switch[1].name == NULL)
+ auth_switch[0].flags |= FLAG_ONEANDONLY;
+
+ /* Initialize auth methods and unconfigure the method if necessary. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->init && IS_CONFIGURED(auth)) {
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER, 0);
+
+ status = (auth->init)(sudo_user.pw, &prompt, auth);
+ if (status == AUTH_FAILURE)
+ auth->flags &= ~FLAG_CONFIGURED;
+ else if (status == AUTH_FATAL) /* XXX log */
+ exit(1); /* assume error msg already printed */
+
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT, 0);
+ }
+ }
+
+ while (--counter) {
+ /* Do any per-method setup and unconfigure the method if needed */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->setup && IS_CONFIGURED(auth)) {
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER, 0);
+
+ status = (auth->setup)(sudo_user.pw, &prompt, auth);
+ if (status == AUTH_FAILURE)
+ auth->flags &= ~FLAG_CONFIGURED;
+ else if (status == AUTH_FATAL) /* XXX log */
+ exit(1); /* assume error msg already printed */
+
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT, 0);
+ }
+ }
+
+ /* Get the password unless the auth function will do it for us */
+ nil_pw = 0;
+#ifdef AUTH_STANDALONE
+ p = prompt;
+#else
+ p = (char *) tgetpass(prompt, def_ival(I_PW_TIMEOUT) * 60, 1);
+ if (!p || *p == '\0')
+ nil_pw = 1;
+#endif /* AUTH_STANDALONE */
+
+ /* Call authentication functions. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (!IS_CONFIGURED(auth))
+ continue;
+
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER, 0);
+
+ success = auth->status = (auth->verify)(sudo_user.pw, p, auth);
+
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT, 0);
+
+ if (auth->status != AUTH_FAILURE)
+ goto cleanup;
+ }
+#ifndef AUTH_STANDALONE
+ (void) memset(p, 0, strlen(p));
+#endif
+
+ /* Exit loop on nil password, but give it a chance to match first. */
+ if (nil_pw) {
+ if (counter == def_ival(I_PW_TRIES))
+ exit(1);
+ else
+ break;
+ }
+
+ pass_warn(stderr);
+ }
+
+cleanup:
+ /* Call cleanup routines. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->cleanup && IS_CONFIGURED(auth)) {
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER, 0);
+
+ status = (auth->cleanup)(sudo_user.pw, auth);
+ if (status == AUTH_FATAL) /* XXX log */
+ exit(1); /* assume error msg already printed */
+
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT, 0);
+ }
+ }
+
+ switch (success) {
+ case AUTH_SUCCESS:
+ return;
+ case AUTH_FAILURE:
+ log_error(NO_MAIL, "%d incorrect password attempt%s",
+ def_ival(I_PW_TRIES) - counter,
+ (def_ival(I_PW_TRIES) - counter == 1) ? "" : "s");
+ case AUTH_FATAL:
+ exit(1);
+ }
+}
+
+void
+pass_warn(fp)
+ FILE *fp;
+{
+
+#ifdef USE_INSULTS
+ (void) fprintf(fp, "%s\n", INSULT);
+#else
+ (void) fprintf(fp, "%s\n", def_str(I_BADPASS_MSG));
+#endif /* USE_INSULTS */
+}
+
+void
+dump_auth_methods()
+{
+ sudo_auth *auth;
+
+ (void) fputs("Authentication methods:", stdout);
+ for (auth = auth_switch; auth->name; auth++)
+ (void) printf(" '%s'", auth->name);
+ (void) putchar('\n');
+}
diff --git a/usr.bin/sudo/auth/sudo_auth.h b/usr.bin/sudo/auth/sudo_auth.h
new file mode 100644
index 00000000000..0b9486d8254
--- /dev/null
+++ b/usr.bin/sudo/auth/sudo_auth.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Sudo: sudo_auth.h,v 1.15 1999/10/13 02:34:55 millert Exp $
+ */
+
+#ifndef SUDO_AUTH_H
+#define SUDO_AUTH_H
+
+/* Auth function return values. */
+#define AUTH_SUCCESS 0
+#define AUTH_FAILURE 1
+#define AUTH_FATAL 2
+
+typedef struct sudo_auth {
+ short flags; /* various flags, see below */
+ short status; /* status from verify routine */
+ char *name; /* name of the method as a string */
+ VOID *data; /* method-specific data pointer */
+ int (*init) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth));
+ int (*setup) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth));
+ int (*verify) __P((struct passwd *pw, char *p, struct sudo_auth *auth));
+ int (*cleanup) __P((struct passwd *pw, struct sudo_auth *auth));
+} sudo_auth;
+
+/* Values for sudo_auth.flags. */
+/* XXX - these names are too long for my liking */
+#define FLAG_USER 0x01 /* functions must run as root */
+#define FLAG_CONFIGURED 0x02 /* method configured ok */
+#define FLAG_ONEANDONLY 0x04 /* one and only auth method */
+
+/* Shortcuts for using the flags above. */
+#define NEEDS_USER(x) ((x)->flags & FLAG_USER)
+#define IS_CONFIGURED(x) ((x)->flags & FLAG_CONFIGURED)
+#define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY)
+
+/* Prototypes for standalone methods */
+int fwtk_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int fwtk_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
+int fwtk_cleanup __P((struct passwd *pw, sudo_auth *auth));
+int pam_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int pam_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
+int pam_cleanup __P((struct passwd *pw, sudo_auth *auth));
+int sia_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int sia_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
+int sia_cleanup __P((struct passwd *pw, sudo_auth *auth));
+int aixauth_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+
+/* Prototypes for normal methods */
+int passwd_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+int secureware_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int secureware_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+int rfc1938_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int rfc1938_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+int afs_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+int dce_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+int kerb4_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int kerb4_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+int kerb5_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int kerb5_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+int kerb5_cleanup __P((struct passwd *pw, sudo_auth *auth));
+int securid_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int securid_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int securid_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
+
+/* Fields: need_root, name, init, setup, verify, cleanup */
+#define AUTH_ENTRY(r, n, i, s, v, c) \
+ { (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c },
+
+/* Some methods cannots (or should not) interoperate with any others */
+#if defined(HAVE_PAM)
+# define AUTH_STANDALONE \
+ AUTH_ENTRY(0, "pam", \
+ pam_init, NULL, pam_verify, pam_cleanup)
+#elif defined(HAVE_SECURID)
+# define AUTH_STANDALONE \
+ AUTH_ENTRY(0, "SecurId", \
+ securid_init, securid_setup, securid_verify, NULL)
+#elif defined(HAVE_SIA)
+# define AUTH_STANDALONE \
+ AUTH_ENTRY(0, "sia", \
+ NULL, sia_setup, sia_verify, sia_cleanup)
+#elif defined(HAVE_AUTHENTICATE)
+# define AUTH_STANDALONE \
+ AUTH_ENTRY(0, "aixauth", \
+ NULL, NULL, aixauth_verify, NULL)
+#elif defined(HAVE_FWTK)
+# define AUTH_STANDALONE \
+ AUTH_ENTRY(0, "fwtk", fwtk_init, \
+ NULL, fwtk_verify, fwtk_cleanup)
+#endif
+
+#endif /* SUDO_AUTH_H */