]> granicus.if.org Git - sudo/commitdiff
New authentication API and methods
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 11 Jul 1999 00:32:11 +0000 (00:32 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 11 Jul 1999 00:32:11 +0000 (00:32 +0000)
12 files changed:
auth/afs.c [new file with mode: 0644]
auth/fwtk.c [new file with mode: 0644]
auth/kerb4.c [new file with mode: 0644]
auth/kerb5.c [new file with mode: 0644]
auth/opie.c [new file with mode: 0644]
auth/pam.c [new file with mode: 0644]
auth/passwd.c [new file with mode: 0644]
auth/secureware.c [new file with mode: 0644]
auth/securid.c [new file with mode: 0644]
auth/skey.c [new file with mode: 0644]
auth/sudo_auth.c [new file with mode: 0644]
auth/sudo_auth.h [new file with mode: 0644]

diff --git a/auth/afs.c b/auth/afs.c
new file mode 100644 (file)
index 0000000..08f31b7
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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$";
+#endif /* lint */
+
+int
+afs_verify(pw, pass, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+    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(user_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,
+                                  user_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/auth/fwtk.c b/auth/fwtk.c
new file mode 100644 (file)
index 0000000..d38b349
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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 <firewall.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+int
+fwtk_setup(pw, promptp, data)
+    struct passwd *pw;
+    char **promptp;
+    void **data;
+{
+    static Cfg *confp;                 /* Configuration entry struct */
+    char resp[128];                    /* Response from the server */
+
+    if (confp)
+       return(AUTH_SUCCESS);           /* Already initialized */
+
+    if ((confp = cfg_read("sudo")) == (Cfg *)-1) {
+       fprintf(stderr, "%s: cannot read fwtk config.\n", Argv[0]);
+       return(AUTH_FATAL);
+    }
+
+    if (auth_open(confp)) {
+       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))) {
+       fprintf(stderr, "%s: lost connection to authentication server.\n",
+           Argv[0]);
+       return(AUTH_FATAL);
+    }
+    if (strncmp(resp, "Authsrv ready", 13) != 0) {
+       fprintf(stderr, "%s: authentication server error.\n%s\n", Argv[0], resp);
+       return(AUTH_FATAL);
+    }
+
+    return(AUTH_SUCCESS);
+}
+
+int
+fwtk_verify(pw, prompt, data)
+    struct passwd *pw;
+    char *prompt;
+    void **data;
+{
+    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) sprintf(buf,"authorize %s 'sudo'", pw->pw_name);
+    if (auth_send(buf) || auth_recv(resp, sizeof(resp))) {
+       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) {
+       sprintf(buf, "%s\nResponse: ", &resp[10]);
+       pass = tgetpass(buf, PASSWORD_TIMEOUT * 60, 0);
+    } else if (strncmp(resp, "password", 8) == 0) {
+       pass = tgetpass(prompt, PASSWORD_TIMEOUT * 60, 1);
+    } else {
+       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 */
+    sprintf(buf, "response '%s'", pass);
+    if (auth_send(buf) || auth_recv(resp, sizeof(resp))) {
+       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, status, data)
+    struct passwd *pw;
+    int status;
+    void **data;
+{
+
+    auth_close();
+}
diff --git a/auth/kerb4.c b/auth/kerb4.c
new file mode 100644 (file)
index 0000000..025c7f1
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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$";
+#endif /* lint */
+
+int
+kerb4_setup(pw, promptp, data)
+    struct passwd *pw;
+    char **promptp;
+    void **data;
+{
+    static char realm[REALM_SZ];
+
+    if (*data)
+       return(AUTH_SUCCESS);           /* Already initialized */
+
+    /* 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) */
+    *data = realm;
+
+    return(AUTH_SUCCESS);
+}
+
+int
+kerb4_verify(pw, pass, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+    char tkfile[sizeof(_PATH_SUDO_TIMEDIR) + 4 + MAX_UID_T_LEN];
+    char *realm = *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/auth/kerb5.c b/auth/kerb5.c
new file mode 100644 (file)
index 0000000..46c6714
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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$";
+#endif /* lint */
+
+char *realm = 0
+static int xrealm = 0
+static krb5_context sudo_context = 0
+
+static int verify_krb_v5_tgt __P((krb5_ccache));
+
+/* XXX - not done yet, need changes to sudo.c */
+int
+kerb5_setup(pw, promptp, data)
+    struct passwd *pw;
+    char **promptp;
+    void **data;
+{
+    krb5_error_code retval;
+    static char *lrealm;
+
+    if (lrealm)
+       return(AUTH_SUCCESS);           /* Already initialized */
+
+    /* XXX - make these errors non-fatal? */
+    if (retval = krb5_init_context(&sudo_context)) {
+       set_perms(PERM_USER, 0);
+       log_error(GLOBAL_KRB5_INIT_ERR);
+       inform_user(GLOBAL_KRB5_INIT_ERR);
+       return(AUTH_FATAL);
+    }
+
+    krb5_init_ets(sudo_context);
+
+    if (retval = krb5_get_default_realm(sudo_context, &lrealm)) {
+       set_perms(PERM_USER, 0);
+       log_error(GLOBAL_KRB5_INIT_ERR);
+       inform_user(GLOBAL_KRB5_INIT_ERR);
+       return(AUTH_FATAL);
+    }
+
+    if (realm) {
+       if (strcmp(realm, lrealm) != 0)
+           xrealm = 1; /* User supplied realm is not the system default */
+       free(lrealm);
+    } else
+       realm = lrealm;
+
+    /* XXX - different default prompt for kerb5 */
+}
+
+int
+kerb5_verify(pw, pass, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+    krb5_error_code    retval;
+    krb5_principal     princ;
+    krb5_creds         creds;
+    krb5_ccache                ccache;
+    char               cache_name[64];
+    char               *princ_name;
+    krb5_get_init_creds_opt opts;
+
+    /* Initialize */
+    if (!sudo_context)
+       return -1;
+    krb5_get_init_creds_opt_init(&opts);
+
+    princ_name = emalloc(strlen(pw->pw_name) + strlen(realm) + 2);
+    (void) sprintf(princ_name, "%s@%s", pw->pw_name, realm);
+    if (krb5_parse_name(sudo_context, princ_name, &princ))
+       return(AUTH_FAILURE);
+
+    /* Set the ticket file to be in /tmp so we don't need to change perms. */
+    (void) sprintf(cache_name, "FILE:/tmp/sudocc_%ld", getpid());
+    if (krb5_cc_resolve(sudo_context, cache_name, &ccache)
+       return(AUTH_FAILURE);
+
+    if (krb5_get_init_creds_password(sudo_context, &creds, princ, pass,
+       krb5_prompter_posix, NULL, 0, NULL, &opts))
+       return(AUTH_FAILURE);
+
+    /* Stash the TGT so we can verify it. */
+    if (krb5_cc_initialize(sudo_context, ccache, princ))
+       return(AUTH_FAILURE);
+    if (krb5_cc_store_cred(sudo_context, ccache, &creds)) {
+       (void) krb5_cc_destroy(sudo_context, ccache);
+       return(AUTH_FAILURE);
+    }
+
+    retval = verify_krb_v5_tgt(ccache);
+    (void) krb5_cc_destroy(sudo_context, ccache);
+    return (retval ? AUTH_FAILURE : 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), let her in.
+ *
+ * Returns 1 for confirmation, -1 for failure, 0 for uncertainty.
+ */
+static int
+verify_krb_v5_tgt(ccache)
+    krb5_ccache                ccache;
+{
+    char               phost[BUFSIZ];
+    krb5_error_code    retval;
+    krb5_principal     princ;
+    krb5_keyblock *    keyblock = 0;
+    krb5_data          packet;
+    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 (krb5_sname_to_principal(sudo_context, NULL, NULL,
+                               KRB5_NT_SRV_HST, &princ))
+       return -1;
+
+    /* Extract the name directly. */
+    strncpy(phost, krb5_princ_component(c, princ, 1)->data, BUFSIZ);
+    phost[BUFSIZ - 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 (retval = krb5_kt_read_service_key(sudo_context, NULL, princ, 0,
+                                         ENCTYPE_DES_CBC_MD5, &keyblock)) {
+       /* Keytab or service key does not exist */
+       if (xrealm)
+           retval = -1;
+       else
+           retval = 0;
+       goto cleanup;
+    }
+    if (keyblock)
+       krb5_free_keyblock(sudo_context, keyblock);
+
+    /* Talk to the kdc and construct the ticket. */
+    retval = 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 */
+    }
+    if (retval) {
+       retval = -1;
+       goto cleanup;
+    }
+
+    /* Try to use the ticket. */
+    retval = krb5_rd_req(sudo_context, &auth_context, &packet, princ,
+                        NULL, NULL, NULL);
+    if (retval) {
+       retval = -1;
+    } else {
+       retval = 1;
+    }
+
+cleanup:
+    if (packet.data)
+       krb5_free_data_contents(sudo_context, &packet);
+    krb5_free_principal(sudo_context, princ);
+    return retval;
+
+}
diff --git a/auth/opie.c b/auth/opie.c
new file mode 100644 (file)
index 0000000..74f2869
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+#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 <opie.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+int
+opie_setup(pw, promptp, data)
+    struct passwd *pw;
+    char **promptp;
+    void **data;
+{
+    char challenge[OPIE_CHALLENGE_MAX];
+    static char *orig_prompt = NULL, *new_prompt = NULL;
+    static int op_len, np_size;
+    static struct opie opie;
+
+    /* Stash a pointer to the opie struct if we have not initialized */
+    if (!*data)
+       *data = &opie;
+
+    /* 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--;
+    }
+
+    /* Get the opie part of the prompt */
+    if (opiechallenge(&opie, user_name, challenge) != 0) {
+#ifdef OTP_ONLY
+       (void) fprintf(stderr,
+                      "%s: You do not exist in the s/key database.\n",
+                      Argv[0]);
+       return(AUTH_FATAL);
+#else
+       return(AUTH_FAILURE);
+#endif /* OTP_ONLY */
+    }
+
+    /* Get space for new prompt with embedded S/Key challenge */
+    if (np_size < op_len + strlen(challenge) + 7) {
+       np_size = op_len + strlen(challenge) + 7;
+       new_prompt = (char *) erealloc(new_prompt, np_size);
+    }
+
+#ifdef 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);
+#endif /* LONG_OTP_PROMPT */
+
+    *promptp = new_prompt;
+    return(AUTH_SUCCESS);
+}
+
+int
+opie_verify(pw, pass, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+    struct opie *opiep = (struct opie *) (*data);
+
+    if (opieverify(opiep, pass) == 0)  
+       return(AUTH_SUCCESS);
+    else
+       return(AUTH_FAILURE);
+}
diff --git a/auth/pam.c b/auth/pam.c
new file mode 100644 (file)
index 0000000..8f3290d
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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$";
+#endif /* lint */
+
+static int sudo_conv __P((int, PAM_CONST struct pam_message **,
+                         struct pam_response **, void *));
+static char *def_prompt;
+
+int
+pam_setup(pw, promptp, data)
+    struct passwd *pw;
+    char **promptp;
+    void **data;
+{
+    static struct pam_conv pam_conv;
+    pam_handle_t *pamh;
+
+    if (*data)
+       return(AUTH_SUCCESS);           /* Already initialized */
+
+    /* Stash prompt */
+    def_prompt = *promptp;
+
+    /* Initial PAM setup */
+    pam_conv.conv = sudo_conv;
+    PAM_nullpw = 0;
+    if (pam_start("sudo", user_name, &pam_conv, &pamh) != PAM_SUCCESS) {
+       set_perms(PERM_USER, 0);
+       log_error(BAD_AUTH_INIT);
+       inform_user(BAD_AUTH_INIT);
+       return(AUTH_FATAL);
+    }
+    *data = pamh;
+    return(AUTH_SUCCESS);
+}
+
+int
+pam_verify(pw, pass, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+    pam_handle_t *pamh = (pam_handle_t *)(*data);
+
+    /* 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, status, data)
+    struct passwd *pw;
+    int status;
+    void **data;
+{
+    pam_handle_t *pamh = (pam_handle_t *)(*data);
+
+    if (pam_end(pamh, (status == AUTH_SUCCESS)) == PAM_SUCCESS)
+       return(AUTH_SUCCESS);
+    else
+       return(AUTH_FAILURE);
+}
+
+/*
+ * sudo_conv()
+ *
+ * ``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 = 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,
+                   PASSWORD_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/auth/passwd.c b/auth/passwd.c
new file mode 100644 (file)
index 0000000..8d78ba3
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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$";
+#endif /* lint */
+
+int
+passwd_verify(pw, pass, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+
+#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/auth/secureware.c b/auth/secureware.c
new file mode 100644 (file)
index 0000000..4a28891
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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
+#  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$";
+#endif /* lint */
+
+int
+secureware_setup(pw, promptp, data)
+    struct passwd *pw;
+    char **promptp;
+    void **data;
+{
+#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, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+#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/auth/securid.c b/auth/securid.c
new file mode 100644 (file)
index 0000000..e93c324
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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$";
+#endif /* lint */
+
+union config_record configure;
+
+int
+securid_setup(pw, promptp, data)
+    struct passwd *pw;
+    char **promptp;
+    void **data;
+{
+    static SD_CLIENT sd_dat;                   /* SecurID data block */
+
+    if (!*data)
+       creadcfg();                             /* Only read config file once */
+
+    /* Initialize SecurID every time. */
+    *data = &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, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+    struct SD_CLIENT *sd = (struct SD_CLIENT *)(*data);
+
+    if (sd_auth(sd) == ACM_OK)
+       return(AUTH_SUCCESS);
+    else
+       return(AUTH_FAILURE);
+}
diff --git a/auth/skey.c b/auth/skey.c
new file mode 100644 (file)
index 0000000..c930a24
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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 <skey.h>
+
+#include "sudo.h"
+#include "sudo_auth.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+int
+skey_setup(pw, promptp, data)
+    struct passwd *pw;
+    char **promptp;
+    void **data;
+{
+    char challenge[256];
+    static char *orig_prompt = NULL, *new_prompt = NULL;
+    static int op_len, np_size;
+    static struct skey skey;
+
+    /* Stash a pointer to the skey struct if we have not initialized */
+    if (!*data)
+       *data = &skey;
+
+    /* 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--;
+    }
+
+    /* Close old stream */
+    if (skey.keyfile)
+       (void) fclose(skey.keyfile);
+
+    /* Get the skey part of the prompt */
+    if (skeychallenge(&skey, user_name, challenge) != 0) {
+#ifdef OTP_ONLY
+       (void) fprintf(stderr,
+                      "%s: You do not exist in the s/key database.\n",
+                      Argv[0]);
+       return(AUTH_FATAL);
+#else
+       return(AUTH_FAILURE);
+#endif /* OTP_ONLY */
+    }
+
+    /* Get space for new prompt with embedded S/Key challenge */
+    if (np_size < op_len + strlen(challenge) + 7) {
+       np_size = op_len + strlen(challenge) + 7;
+       new_prompt = (char *) erealloc(new_prompt, np_size);
+    }
+
+#ifdef 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);
+#endif /* LONG_OTP_PROMPT */
+
+    *promptp = new_prompt;
+    return(AUTH_SUCCESS);
+}
+
+int
+skey_verify(pw, pass, data)
+    struct passwd *pw;
+    char *pass;
+    void **data;
+{
+    struct skey *skeyp = (struct skey *) (*data);
+
+    if (skeyverify(skeyp, pass) == 0)
+       return(AUTH_SUCCESS);
+    else
+       return(AUTH_FAILURE);
+}
diff --git a/auth/sudo_auth.c b/auth/sudo_auth.c
new file mode 100644 (file)
index 0000000..c5780d2
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *  CU sudo version 1.6
+ *  Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ *  This program 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 1, or (at your option)
+ *  any later version.
+ *
+ *  This program 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.
+ *
+ *  Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ */
+
+#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"
+#include "insults.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+sudo_auth auth_switch[] = {
+#ifdef AUTH_STANDALONE
+    AUTH_STANDALONE
+#else
+    AUTH_ENTRY(0, "passwd", NULL, passwd_verify, NULL)
+#  ifdef HAVE_SECUREWARE
+    AUTH_ENTRY(0, "secureware", secureware_setup, secureware_verify, NULL)
+#  endif
+#  ifdef HAVE_SKEY
+    AUTH_ENTRY(1, "skey", skey_setup, skey_verify, NULL)
+#  endif
+#  ifdef HAVE_OPIE
+    AUTH_ENTRY(1, "opie", opie_setup, opie_verify, NULL)
+#  endif
+#  ifdef HAVE_AFS
+    AUTH_ENTRY(1, "afs", NULL, afs_verify, NULL)
+#  endif
+#  ifdef HAVE_KERB4
+    AUTH_ENTRY(1, "kerb4", kerb4_setup, kerb4_verify, NULL)
+#  endif
+#  ifdef HAVE_KERB5
+    AUTH_ENTRY(1, "kerb5", kerb5_setup, kerb5_verify, NULL)
+#  endif
+#endif /* AUTH_STANDALONE */
+    AUTH_ENTRY(0, NULL, NULL, NULL, NULL)
+};
+
+int nil_pw; /* bad global, bad (oh well) */
+
+void
+/* verify_user() */
+check_passwd()
+{
+    int counter = TRIES_FOR_PASSWORD + 1;
+    int status, success = AUTH_FAILURE;
+    char *p;
+    sudo_auth *auth;
+
+    while (--counter) {
+       /* Do any per-method setup and unconfigure the method if needed */
+       for (auth = auth_switch; auth->name; auth++) {
+           if (auth->setup && auth->configured) {
+               if (auth->need_root)
+                   set_perms(PERM_ROOT, 0);
+
+               status = (auth->setup)(user_pw_ent, &prompt, &auth->data);
+               if (status == AUTH_FAILURE)
+                   auth->configured = 0;
+               else if (status == AUTH_FATAL)  /* XXX log */
+                   exit(1);            /* assume error msg already printed */
+
+               if (auth->need_root)
+                   set_perms(PERM_USER, 0);
+           }
+       }
+
+       /* Get the password unless the auth function will do it for us */
+       nil_pw = 0;
+#if defined(AUTH_STANDALONE) && !defined(AUTH_STANDALONE_GETPASS)
+       p = prompt;
+#else
+       p = (char *) tgetpass(prompt, PASSWORD_TIMEOUT * 60, 1);
+       if (!p || *p == '\0')
+           nil_pw = 1;
+#endif /* AUTH_STANDALONE */
+
+       /* Call authentication functions. */
+       for (auth = auth_switch; auth->name; auth++) {
+           if (!auth->configured)
+               continue;
+
+           if (auth->need_root)
+               set_perms(PERM_ROOT, 0);
+
+           success = auth->status = (auth->verify)(user_pw_ent, p, &auth->data);
+
+           if (auth->need_root)
+               set_perms(PERM_USER, 0);
+
+           if (auth->status != AUTH_FAILURE)
+               goto cleanup;
+       }
+
+       /* Exit loop on nil password, but give it a chance to match first. */
+       if (nil_pw) {
+           if (counter == TRIES_FOR_PASSWORD)
+               exit(1);
+           else
+               break;
+       }
+
+       pass_warn(stderr);
+    }
+
+cleanup:
+    /* Call cleanup routines. */
+    for (auth = auth_switch; auth->name; auth++) {
+       if (auth->cleanup && auth->configured) {
+           if (auth->need_root)
+               set_perms(PERM_ROOT, 0);
+
+           status = (auth->cleanup)(user_pw_ent, auth->status, &auth->data);
+           if (status == AUTH_FATAL)   /* XXX log */
+               exit(1);                /* assume error msg already printed */
+
+           if (auth->need_root)
+               set_perms(PERM_USER, 0);
+       }
+    }
+
+    switch (success) {
+       case AUTH_SUCCESS:
+           return;
+       case AUTH_FAILURE:
+           log_error(counter ? PASSWORD_NOT_CORRECT : PASSWORDS_NOT_CORRECT);
+           inform_user(counter ? PASSWORD_NOT_CORRECT : PASSWORDS_NOT_CORRECT);
+       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", INCORRECT_PASSWORD);
+#endif /* USE_INSULTS */
+}
diff --git a/auth/sudo_auth.h b/auth/sudo_auth.h
new file mode 100644 (file)
index 0000000..1974c8a
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef SUDO_AUTH_H
+#define SUDO_AUTH_H
+
+#define AUTH_SUCCESS   0
+#define AUTH_FAILURE   1
+#define AUTH_FATAL     2
+
+typedef struct sudo_auth {
+    int need_root;             /* must run as root? */
+    int configured;            /* auth type configured on this host? */
+    int status;                        /* status from verify routine */
+    char *name;
+    void *data;                        /* method-specific data pointer */
+    int (*setup) __P((struct passwd *pw, char **prompt, void **data));
+    int (*verify) __P((struct passwd *pw, char *p, void **data));
+    int (*cleanup) __P((struct passwd *pw, int status, void **data));
+} sudo_auth;
+
+/* Prototypes for standalone methods */
+int fwtk_setup __P((struct passwd *pw, char **prompt, void **data));
+int fwtk_verify __P((struct passwd *pw, char *prompt, void **data));
+int fwtk_cleanup __P((struct passwd *pw, int status, void **data));
+int pam_setup __P((struct passwd *pw, char **prompt, void **data));
+int pam_verify __P((struct passwd *pw, char *prompt, void **data));
+int pam_cleanup __P((struct passwd *pw, int status, void **data));
+
+/* Prototypes for normal methods */
+int passwd_verify __P((struct passwd *pw, char *pass, void **data));
+int secureware_setup __P((struct passwd *pw, char **prompt, void **data));
+int secureware_verify __P((struct passwd *pw, char *pass, void **data));
+int skey_setup __P((struct passwd *pw, char **prompt, void **data));
+int skey_verify __P((struct passwd *pw, char *pass, void **data));
+int opie_setup __P((struct passwd *pw, char **prompt, void **data));
+int opie_verify __P((struct passwd *pw, char *pass, void **data));
+int afs_verify __P((struct passwd *pw, char *pass, void **data));
+int kerb4_setup __P((struct passwd *pw, char **prompt, void **data));
+int kerb4_verify __P((struct passwd *pw, char *pass, void **data));
+int kerb5_setup __P((struct passwd *pw, char **prompt, void **data));
+int kerb5_verify __P((struct passwd *pw, char *pass, void **data));
+
+/* Fields: need_root, name, setup, verify, cleanup */
+#define AUTH_ENTRY(r, n, s, v, c) { r, 1, AUTH_FAILURE, n, NULL, s, v, c },
+
+/* Some methods cannots (or should not) interoperate with any others */
+#if defined(HAVE_PAM)
+#  define AUTH_STANDALONE \
+       AUTH_ENTRY(1, "pam", pam_setup, passwd_verify, pam_cleanup)
+#elif defined(HAVE_SECURID)
+#  define AUTH_STANDALONE \
+       AUTH_ENTRY(1, "SecurId", securid_setup, securid_verify, NULL)
+#elif defined(HAVE_FWTK)
+#  define AUTH_STANDALONE \
+       AUTH_ENTRY(1, "fwtk", fwtk_setup, fwtk_verify, fwtk_cleanup)
+#elif defined(HAVE_SKEY) && defined(OTP_ONLY)
+#  define AUTH_STANDALONE \
+       AUTH_ENTRY(1, "skey", skey_setup, skey_verify, NULL)
+#  define AUTH_STANDALONE_GETPASS
+#elif defined(HAVE_OPIE) && defined(OTP_ONLY)
+#  define AUTH_STANDALONE \
+       AUTH_ENTRY(1, "opie", opie_setup, opie_verify, NULL)
+#  define AUTH_STANDALONE_GETPASS
+#endif
+
+#endif /* SUDO_AUTH_H */