Rework source layout in preparation for modular sudo.
This commit is contained in:
128
plugins/sudoers/auth/API
Normal file
128
plugins/sudoers/auth/API
Normal file
@@ -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.
|
87
plugins/sudoers/auth/afs.c
Normal file
87
plugins/sudoers/auth/afs.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2001-2005, 2007
|
||||
* Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
#include <afs/stds.h>
|
||||
#include <afs/kautils.h>
|
||||
|
||||
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);
|
||||
}
|
84
plugins/sudoers/auth/aix_auth.c
Normal file
84
plugins/sudoers/auth/aix_auth.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007-2009 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
/*
|
||||
* For a description of the AIX authentication API, see
|
||||
* http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/basetrf1/authenticate.htm
|
||||
*/
|
||||
int
|
||||
aixauth_verify(pw, prompt, auth)
|
||||
struct passwd *pw;
|
||||
char *prompt;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
char *pass;
|
||||
char *message = NULL;
|
||||
int reenter = 1;
|
||||
int rval = AUTH_FAILURE;
|
||||
|
||||
pass = tgetpass(prompt, def_passwd_timeout * 60, tgetpass_flags);
|
||||
if (pass) {
|
||||
/* XXX - should probably print message on failure. */
|
||||
if (authenticate(pw->pw_name, pass, &reenter, &message) == 0)
|
||||
rval = AUTH_SUCCESS;
|
||||
free(message);
|
||||
zero_bytes(pass, strlen(pass));
|
||||
}
|
||||
return(rval);
|
||||
}
|
||||
|
||||
int
|
||||
aixauth_cleanup(pw, auth)
|
||||
struct passwd *pw;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
/* Unset AUTHSTATE as it may not be correct for the runas user. */
|
||||
unsetenv("AUTHSTATE");
|
||||
|
||||
return(AUTH_SUCCESS);
|
||||
}
|
169
plugins/sudoers/auth/bsdauth.c
Normal file
169
plugins/sudoers/auth/bsdauth.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005, 2007-2008 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <login_cap.h>
|
||||
#include <bsd_auth.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
extern char *login_style; /* from sudo.c */
|
||||
|
||||
int
|
||||
bsdauth_init(pw, promptp, auth)
|
||||
struct passwd *pw;
|
||||
char **promptp;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
static auth_session_t *as;
|
||||
extern login_cap_t *lc; /* from sudo.c */
|
||||
|
||||
if ((as = auth_open()) == NULL) {
|
||||
log_error(USE_ERRNO|NO_EXIT|NO_MAIL,
|
||||
"unable to begin bsd authentication");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
/* XXX - maybe sanity check the auth style earlier? */
|
||||
login_style = login_getstyle(lc, login_style, "auth-sudo");
|
||||
if (login_style == NULL) {
|
||||
log_error(NO_EXIT|NO_MAIL, "invalid authentication type");
|
||||
auth_close(as);
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
if (auth_setitem(as, AUTHV_STYLE, login_style) < 0 ||
|
||||
auth_setitem(as, AUTHV_NAME, pw->pw_name) < 0 ||
|
||||
auth_setitem(as, AUTHV_CLASS, login_class) < 0) {
|
||||
log_error(NO_EXIT|NO_MAIL, "unable to setup authentication");
|
||||
auth_close(as);
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
auth->data = (void *) as;
|
||||
return(AUTH_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
bsdauth_verify(pw, prompt, auth)
|
||||
struct passwd *pw;
|
||||
char *prompt;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
char *pass;
|
||||
char *s;
|
||||
size_t len;
|
||||
int authok = 0;
|
||||
sigaction_t sa, osa;
|
||||
auth_session_t *as = (auth_session_t *) auth->data;
|
||||
|
||||
/* save old signal handler */
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
(void) sigaction(SIGCHLD, &sa, &osa);
|
||||
|
||||
/*
|
||||
* If there is a challenge then print that instead of the normal
|
||||
* prompt. If the user just hits return we prompt again with echo
|
||||
* turned on, which is useful for challenge/response things like
|
||||
* S/Key.
|
||||
*/
|
||||
if ((s = auth_challenge(as)) == NULL) {
|
||||
pass = tgetpass(prompt, def_passwd_timeout * 60, tgetpass_flags);
|
||||
} else {
|
||||
pass = tgetpass(s, def_passwd_timeout * 60, tgetpass_flags);
|
||||
if (pass && *pass == '\0') {
|
||||
if ((prompt = strrchr(s, '\n')))
|
||||
prompt++;
|
||||
else
|
||||
prompt = s;
|
||||
|
||||
/*
|
||||
* Append '[echo on]' to the last line of the challenge and
|
||||
* reprompt with echo turned on.
|
||||
*/
|
||||
len = strlen(prompt) - 1;
|
||||
while (isspace(prompt[len]) || prompt[len] == ':')
|
||||
prompt[len--] = '\0';
|
||||
easprintf(&s, "%s [echo on]: ", prompt);
|
||||
pass = tgetpass(s, def_passwd_timeout * 60,
|
||||
tgetpass_flags | TGP_ECHO);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (pass) {
|
||||
authok = auth_userresponse(as, pass, 1);
|
||||
zero_bytes(pass, strlen(pass));
|
||||
}
|
||||
|
||||
/* restore old signal handler */
|
||||
(void) sigaction(SIGCHLD, &osa, NULL);
|
||||
|
||||
if (authok)
|
||||
return(AUTH_SUCCESS);
|
||||
|
||||
if (!pass)
|
||||
return(AUTH_INTR);
|
||||
|
||||
if ((s = auth_getvalue(as, "errormsg")) != NULL)
|
||||
log_error(NO_EXIT|NO_MAIL, "%s", s);
|
||||
return(AUTH_FAILURE);
|
||||
}
|
||||
|
||||
int
|
||||
bsdauth_cleanup(pw, auth)
|
||||
struct passwd *pw;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
auth_session_t *as = (auth_session_t *) auth->data;
|
||||
|
||||
auth_close(as);
|
||||
|
||||
return(AUTH_SUCCESS);
|
||||
}
|
202
plugins/sudoers/auth/dce.c
Normal file
202
plugins/sudoers/auth/dce.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 1998-2005 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
* 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.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_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"
|
||||
|
||||
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);
|
||||
}
|
159
plugins/sudoers/auth/fwtk.c
Normal file
159
plugins/sudoers/auth/fwtk.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2008 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
|
||||
#include <auth.h>
|
||||
#include <firewall.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
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) {
|
||||
warningx("cannot read fwtk config");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
if (auth_open(confp)) {
|
||||
warningx("cannot connect to authentication server");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
/* Get welcome message from auth server */
|
||||
if (auth_recv(resp, sizeof(resp))) {
|
||||
warningx("lost connection to authentication server");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
if (strncmp(resp, "Authsrv ready", 13) != 0) {
|
||||
warningx("authentication server error:\n%s", 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 */
|
||||
int error;
|
||||
|
||||
/* Send username to authentication server. */
|
||||
(void) snprintf(buf, sizeof(buf), "authorize %s 'sudo'", pw->pw_name);
|
||||
restart:
|
||||
if (auth_send(buf) || auth_recv(resp, sizeof(resp))) {
|
||||
warningx("lost connection to authentication server");
|
||||
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_passwd_timeout * 60, tgetpass_flags);
|
||||
if (pass && *pass == '\0') {
|
||||
pass = tgetpass("Response [echo on]: ",
|
||||
def_passwd_timeout * 60, tgetpass_flags | TGP_ECHO);
|
||||
}
|
||||
} else if (strncmp(resp, "chalnecho ", 10) == 0) {
|
||||
pass = tgetpass(&resp[10], def_passwd_timeout * 60, tgetpass_flags);
|
||||
} else if (strncmp(resp, "password", 8) == 0) {
|
||||
pass = tgetpass(prompt, def_passwd_timeout * 60,
|
||||
tgetpass_flags);
|
||||
} else if (strncmp(resp, "display ", 8) == 0) {
|
||||
fprintf(stderr, "%s\n", &resp[8]);
|
||||
strlcpy(buf, "response dummy", sizeof(buf));
|
||||
goto restart;
|
||||
} else {
|
||||
warningx("%s", resp);
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
if (!pass) { /* ^C or error */
|
||||
return(AUTH_INTR);
|
||||
}
|
||||
|
||||
/* 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))) {
|
||||
warningx("lost connection to authentication server");
|
||||
error = AUTH_FATAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (strncmp(resp, "ok", 2) == 0) {
|
||||
error = AUTH_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Main loop prints "Permission Denied" or insult. */
|
||||
if (strcmp(resp, "Permission Denied.") != 0)
|
||||
warningx("%s", resp);
|
||||
error = AUTH_FAILURE;
|
||||
done:
|
||||
zero_bytes(pass, strlen(pass));
|
||||
zero_bytes(buf, strlen(buf));
|
||||
return(error);
|
||||
}
|
||||
|
||||
int
|
||||
fwtk_cleanup(pw, auth)
|
||||
struct passwd *pw;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
|
||||
auth_close();
|
||||
return(AUTH_SUCCESS);
|
||||
}
|
108
plugins/sudoers/auth/kerb4.c
Normal file
108
plugins/sudoers/auth/kerb4.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
#include <krb.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
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) snprintf(tkfile, sizeof(tkfile), "%s/tkt%lu",
|
||||
_PATH_SUDO_TIMEDIR, (unsigned 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);
|
||||
}
|
319
plugins/sudoers/auth/kerb5.c
Normal file
319
plugins/sudoers/auth/kerb5.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007-2008 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
* 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.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
#include <krb5.h>
|
||||
#ifdef HAVE_HEIMDAL
|
||||
#include <com_err.h>
|
||||
#endif
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
#ifdef HAVE_HEIMDAL
|
||||
# define extract_name(c, p) krb5_principal_get_comp_string(c, p, 1)
|
||||
# define krb5_free_data_contents(c, d) krb5_data_free(d)
|
||||
#else
|
||||
# define extract_name(c, p) (krb5_princ_component(c, p, 1)->data)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_KRB5_VERIFY_USER
|
||||
static int verify_krb_v5_tgt __P((krb5_context, krb5_creds *, char *));
|
||||
#endif
|
||||
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;
|
||||
|
||||
#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
|
||||
static krb5_error_code
|
||||
krb5_get_init_creds_opt_alloc(context, opts)
|
||||
krb5_context context;
|
||||
krb5_get_init_creds_opt **opts;
|
||||
{
|
||||
*opts = emalloc(sizeof(krb5_get_init_creds_opt));
|
||||
krb5_get_init_creds_opt_init(*opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
krb5_get_init_creds_opt_free(opts)
|
||||
krb5_get_init_creds_opt *opts;
|
||||
{
|
||||
free(opts);
|
||||
}
|
||||
#endif
|
||||
|
||||
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 */
|
||||
|
||||
#ifdef HAVE_KRB5_INIT_SECURE_CONTEXT
|
||||
error = krb5_init_secure_context(&(sudo_krb5_data.sudo_context));
|
||||
#else
|
||||
error = krb5_init_context(&(sudo_krb5_data.sudo_context));
|
||||
#endif
|
||||
if (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
|
||||
|
||||
(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;
|
||||
|
||||
return(AUTH_SUCCESS);
|
||||
}
|
||||
|
||||
#ifdef HAVE_KRB5_VERIFY_USER
|
||||
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_error_code error;
|
||||
|
||||
sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
|
||||
princ = ((sudo_krb5_datap) auth->data)->princ;
|
||||
ccache = ((sudo_krb5_datap) auth->data)->ccache;
|
||||
|
||||
error = krb5_verify_user(sudo_context, princ, ccache, pass, 1, NULL);
|
||||
return (error ? AUTH_FAILURE : AUTH_SUCCESS);
|
||||
}
|
||||
#else
|
||||
int
|
||||
kerb5_verify(pw, pass, auth)
|
||||
struct passwd *pw;
|
||||
char *pass;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
krb5_context sudo_context;
|
||||
krb5_principal princ;
|
||||
krb5_creds credbuf, *creds = NULL;
|
||||
krb5_ccache ccache;
|
||||
krb5_error_code error;
|
||||
krb5_get_init_creds_opt *opts = NULL;
|
||||
|
||||
sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
|
||||
princ = ((sudo_krb5_datap) auth->data)->princ;
|
||||
ccache = ((sudo_krb5_datap) auth->data)->ccache;
|
||||
|
||||
/* Set default flags based on the local config file. */
|
||||
error = krb5_get_init_creds_opt_alloc(sudo_context, &opts);
|
||||
if (error) {
|
||||
log_error(NO_EXIT|NO_MAIL,
|
||||
"%s: unable to allocate options: %s", auth->name,
|
||||
error_message(error));
|
||||
goto done;
|
||||
}
|
||||
#ifdef HAVE_HEIMDAL
|
||||
krb5_get_init_creds_opt_set_default_flags(sudo_context, NULL,
|
||||
krb5_principal_get_realm(sudo_context, princ), opts);
|
||||
#endif
|
||||
|
||||
/* Note that we always obtain a new TGT to verify the user */
|
||||
if ((error = krb5_get_init_creds_password(sudo_context, &credbuf, princ,
|
||||
pass, krb5_prompter_posix,
|
||||
NULL, 0, NULL, opts))) {
|
||||
/* Don't print error if just a bad password */
|
||||
if (error != KRB5KRB_AP_ERR_BAD_INTEGRITY)
|
||||
log_error(NO_EXIT|NO_MAIL,
|
||||
"%s: unable to get credentials: %s", auth->name,
|
||||
error_message(error));
|
||||
goto done;
|
||||
}
|
||||
creds = &credbuf;
|
||||
|
||||
/* Verify the TGT to prevent spoof attacks. */
|
||||
if ((error = verify_krb_v5_tgt(sudo_context, creds, auth->name)))
|
||||
goto done;
|
||||
|
||||
/* Store cred in cred cache. */
|
||||
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));
|
||||
} else if ((error = krb5_cc_store_cred(sudo_context, ccache, creds))) {
|
||||
log_error(NO_EXIT|NO_MAIL,
|
||||
"%s: unable to store cred in ccache: %s", auth->name,
|
||||
error_message(error));
|
||||
}
|
||||
|
||||
done:
|
||||
if (opts) {
|
||||
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS
|
||||
krb5_get_init_creds_opt_free(sudo_context, opts);
|
||||
#else
|
||||
krb5_get_init_creds_opt_free(opts);
|
||||
#endif
|
||||
}
|
||||
if (creds)
|
||||
krb5_free_cred_contents(sudo_context, creds);
|
||||
return (error ? AUTH_FAILURE : AUTH_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifndef HAVE_KRB5_VERIFY_USER
|
||||
/*
|
||||
* 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).
|
||||
*
|
||||
* Returns 0 for successful authentication, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
verify_krb_v5_tgt(sudo_context, cred, auth_name)
|
||||
krb5_context sudo_context;
|
||||
krb5_creds *cred;
|
||||
char *auth_name; /* For error reporting */
|
||||
{
|
||||
krb5_error_code error;
|
||||
krb5_principal server;
|
||||
krb5_verify_init_creds_opt vopt;
|
||||
|
||||
/*
|
||||
* 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, &server))) {
|
||||
log_error(NO_EXIT|NO_MAIL,
|
||||
"%s: unable to get host principal: %s", auth_name,
|
||||
error_message(error));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Initialize verify opts and set secure mode */
|
||||
krb5_verify_init_creds_opt_init(&vopt);
|
||||
krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, 1);
|
||||
|
||||
/* verify the Kerberos ticket-granting ticket we just retrieved */
|
||||
error = krb5_verify_init_creds(sudo_context, cred, server, NULL,
|
||||
NULL, &vopt);
|
||||
krb5_free_principal(sudo_context, server);
|
||||
if (error)
|
||||
log_error(NO_EXIT|NO_MAIL,
|
||||
"%s: Cannot verify TGT! Possible attack!: %s", auth_name,
|
||||
error_message(error));
|
||||
return(error);
|
||||
}
|
||||
#endif
|
336
plugins/sudoers/auth/pam.c
Normal file
336
plugins/sudoers/auth/pam.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007-2009 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
|
||||
# include <memory.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_PAM_PAM_APPL_H
|
||||
# include <pam/pam_appl.h>
|
||||
#else
|
||||
# include <security/pam_appl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DGETTEXT
|
||||
# include <libintl.h>
|
||||
# if defined(__LINUX_PAM__)
|
||||
# define PAM_TEXT_DOMAIN "Linux-PAM"
|
||||
# elif defined(__sun__)
|
||||
# define PAM_TEXT_DOMAIN "SUNW_OST_SYSOSPAM"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
/* Only OpenPAM and Linux PAM use const qualifiers. */
|
||||
#if defined(_OPENPAM) || defined(__LIBPAM_VERSION) || defined(__LINUX_PAM__)
|
||||
# define PAM_CONST const
|
||||
#else
|
||||
# define PAM_CONST
|
||||
#endif
|
||||
|
||||
static int sudo_conv __P((int, PAM_CONST struct pam_message **,
|
||||
struct pam_response **, void *));
|
||||
static char *def_prompt = "Password:";
|
||||
static int gotintr;
|
||||
|
||||
#ifndef PAM_DATA_SILENT
|
||||
#define PAM_DATA_SILENT 0
|
||||
#endif
|
||||
|
||||
static pam_handle_t *pamh; /* global due to pam_prep_user() */
|
||||
|
||||
int
|
||||
pam_init(pw, promptp, auth)
|
||||
struct passwd *pw;
|
||||
char **promptp;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
static struct pam_conv pam_conv;
|
||||
static int pam_status;
|
||||
|
||||
/* Initial PAM setup */
|
||||
if (auth != NULL)
|
||||
auth->data = (void *) &pam_status;
|
||||
pam_conv.conv = sudo_conv;
|
||||
pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh);
|
||||
if (pam_status != PAM_SUCCESS) {
|
||||
log_error(USE_ERRNO|NO_EXIT|NO_MAIL, "unable to initialize PAM");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set PAM_RUSER to the invoking user (the "from" user).
|
||||
* We set PAM_RHOST to avoid a bug in Solaris 7 and below.
|
||||
*/
|
||||
(void) pam_set_item(pamh, PAM_RUSER, user_name);
|
||||
(void) pam_set_item(pamh, PAM_RHOST, user_host);
|
||||
|
||||
/*
|
||||
* Some versions of pam_lastlog have a bug that
|
||||
* will cause a crash if PAM_TTY is not set so if
|
||||
* there is no tty, set PAM_TTY to the empty string.
|
||||
*/
|
||||
if (user_ttypath == NULL)
|
||||
(void) pam_set_item(pamh, PAM_TTY, "");
|
||||
else
|
||||
(void) pam_set_item(pamh, PAM_TTY, user_ttypath);
|
||||
|
||||
return(AUTH_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
pam_verify(pw, prompt, auth)
|
||||
struct passwd *pw;
|
||||
char *prompt;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
const char *s;
|
||||
int *pam_status = (int *) auth->data;
|
||||
|
||||
def_prompt = prompt; /* for sudo_conv */
|
||||
|
||||
/* PAM_SILENT prevents the authentication service from generating output. */
|
||||
*pam_status = pam_authenticate(pamh, PAM_SILENT);
|
||||
switch (*pam_status) {
|
||||
case PAM_SUCCESS:
|
||||
*pam_status = pam_acct_mgmt(pamh, PAM_SILENT);
|
||||
switch (*pam_status) {
|
||||
case PAM_SUCCESS:
|
||||
return(AUTH_SUCCESS);
|
||||
case PAM_AUTH_ERR:
|
||||
log_error(NO_EXIT|NO_MAIL, "pam_acct_mgmt: %d",
|
||||
*pam_status);
|
||||
return(AUTH_FAILURE);
|
||||
case PAM_NEW_AUTHTOK_REQD:
|
||||
log_error(NO_EXIT|NO_MAIL, "%s, %s",
|
||||
"Account or password is expired",
|
||||
"reset your password and try again");
|
||||
*pam_status = pam_chauthtok(pamh,
|
||||
PAM_CHANGE_EXPIRED_AUTHTOK);
|
||||
if (*pam_status == PAM_SUCCESS)
|
||||
return(AUTH_SUCCESS);
|
||||
if ((s = pam_strerror(pamh, *pam_status)))
|
||||
log_error(NO_EXIT|NO_MAIL, "pam_chauthtok: %s", s);
|
||||
return(AUTH_FAILURE);
|
||||
case PAM_AUTHTOK_EXPIRED:
|
||||
log_error(NO_EXIT|NO_MAIL,
|
||||
"Password expired, contact your system administrator");
|
||||
return(AUTH_FATAL);
|
||||
case PAM_ACCT_EXPIRED:
|
||||
log_error(NO_EXIT|NO_MAIL, "%s %s",
|
||||
"Account expired or PAM config lacks an \"account\"",
|
||||
"section for sudo, contact your system administrator");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case PAM_AUTH_ERR:
|
||||
if (gotintr) {
|
||||
/* error or ^C from tgetpass() */
|
||||
return(AUTH_INTR);
|
||||
}
|
||||
case PAM_MAXTRIES:
|
||||
case PAM_PERM_DENIED:
|
||||
return(AUTH_FAILURE);
|
||||
default:
|
||||
if ((s = pam_strerror(pamh, *pam_status)))
|
||||
log_error(NO_EXIT|NO_MAIL, "pam_authenticate: %s", s);
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pam_cleanup(pw, auth)
|
||||
struct passwd *pw;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
int *pam_status = (int *) auth->data;
|
||||
|
||||
/* If successful, we can't close the session until pam_prep_user() */
|
||||
if (auth->status == AUTH_SUCCESS)
|
||||
return(AUTH_SUCCESS);
|
||||
|
||||
*pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT);
|
||||
return(*pam_status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||
}
|
||||
|
||||
int
|
||||
pam_prep_user(pw)
|
||||
struct passwd *pw;
|
||||
{
|
||||
int eval;
|
||||
|
||||
if (pamh == NULL)
|
||||
pam_init(pw, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Update PAM_USER to reference the user we are running the command
|
||||
* as, as opposed to the user we authenticated as.
|
||||
*/
|
||||
(void) pam_set_item(pamh, PAM_USER, pw->pw_name);
|
||||
|
||||
/*
|
||||
* Set credentials (may include resource limits, device ownership, etc).
|
||||
* We don't check the return value here because in Linux-PAM 0.75
|
||||
* it returns the last saved return code, not the return code
|
||||
* for the setcred module. Because we haven't called pam_authenticate(),
|
||||
* this is not set and so pam_setcred() returns PAM_PERM_DENIED.
|
||||
* We can't call pam_acct_mgmt() with Linux-PAM for a similar reason.
|
||||
*/
|
||||
(void) pam_setcred(pamh, PAM_ESTABLISH_CRED);
|
||||
|
||||
#ifndef NO_PAM_SESSION
|
||||
/*
|
||||
* To fully utilize PAM sessions we would need to keep a
|
||||
* sudo process around until the command exits. However, we
|
||||
* can at least cause pam_limits to be run by opening and then
|
||||
* immediately closing the session.
|
||||
*/
|
||||
if ((eval = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
|
||||
(void) pam_end(pamh, eval | PAM_DATA_SILENT);
|
||||
return(AUTH_FAILURE);
|
||||
}
|
||||
(void) pam_close_session(pamh, 0);
|
||||
#endif
|
||||
|
||||
if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) == PAM_SUCCESS)
|
||||
return(AUTH_SUCCESS);
|
||||
else
|
||||
return(AUTH_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* ``Conversation function'' for PAM.
|
||||
* XXX - does not handle PAM_BINARY_PROMPT
|
||||
*/
|
||||
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;
|
||||
PAM_CONST struct pam_message *pm;
|
||||
const char *prompt;
|
||||
char *pass;
|
||||
int n, flags, std_prompt;
|
||||
|
||||
if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL)
|
||||
return(PAM_SYSTEM_ERR);
|
||||
zero_bytes(*response, num_msg * sizeof(struct pam_response));
|
||||
|
||||
for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) {
|
||||
flags = tgetpass_flags;
|
||||
switch (pm->msg_style) {
|
||||
case PAM_PROMPT_ECHO_ON:
|
||||
SET(flags, TGP_ECHO);
|
||||
case PAM_PROMPT_ECHO_OFF:
|
||||
prompt = def_prompt;
|
||||
|
||||
/* Is the sudo prompt standard? (If so, we'l just use PAM's) */
|
||||
std_prompt = strncmp(def_prompt, "Password:", 9) == 0 &&
|
||||
(def_prompt[9] == '\0' ||
|
||||
(def_prompt[9] == ' ' && def_prompt[10] == '\0'));
|
||||
|
||||
/* Only override PAM prompt if it matches /^Password: ?/ */
|
||||
#if defined(PAM_TEXT_DOMAIN) && defined(HAVE_DGETTEXT)
|
||||
if (!def_passprompt_override && (std_prompt ||
|
||||
(strcmp(pm->msg, dgettext(PAM_TEXT_DOMAIN, "Password: ")) &&
|
||||
strcmp(pm->msg, dgettext(PAM_TEXT_DOMAIN, "Password:")))))
|
||||
prompt = pm->msg;
|
||||
#else
|
||||
if (!def_passprompt_override && (std_prompt ||
|
||||
strncmp(pm->msg, "Password:", 9) || (pm->msg[9] != '\0'
|
||||
&& (pm->msg[9] != ' ' || pm->msg[10] != '\0'))))
|
||||
prompt = pm->msg;
|
||||
#endif
|
||||
/* Read the password unless interrupted. */
|
||||
pass = tgetpass(prompt, def_passwd_timeout * 60, flags);
|
||||
if (pass == NULL) {
|
||||
/* We got ^C instead of a password; abort quickly. */
|
||||
if (errno == EINTR)
|
||||
gotintr = 1;
|
||||
#if defined(__darwin__) || defined(__APPLE__)
|
||||
pass = "";
|
||||
#else
|
||||
goto err;
|
||||
#endif
|
||||
}
|
||||
pr->resp = estrdup(pass);
|
||||
zero_bytes(pass, strlen(pass));
|
||||
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:
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return(PAM_SUCCESS);
|
||||
|
||||
err:
|
||||
/* Zero and free allocated memory and return an error. */
|
||||
for (pr = *response, n = num_msg; n--; pr++) {
|
||||
if (pr->resp != NULL) {
|
||||
zero_bytes(pr->resp, strlen(pr->resp));
|
||||
free(pr->resp);
|
||||
pr->resp = NULL;
|
||||
}
|
||||
}
|
||||
zero_bytes(*response, num_msg * sizeof(struct pam_response));
|
||||
free(*response);
|
||||
*response = NULL;
|
||||
return(gotintr ? PAM_AUTH_ERR : PAM_CONV_ERR);
|
||||
}
|
105
plugins/sudoers/auth/passwd.c
Normal file
105
plugins/sudoers/auth/passwd.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
#define DESLEN 13
|
||||
#define HAS_AGEINFO(p, l) (l == 18 && p[DESLEN] == ',')
|
||||
|
||||
int
|
||||
passwd_init(pw, promptp, auth)
|
||||
struct passwd *pw;
|
||||
char **promptp;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
#ifdef HAVE_SKEYACCESS
|
||||
if (skeyaccess(pw, user_tty, NULL, NULL) == 0)
|
||||
return(AUTH_FAILURE);
|
||||
#endif
|
||||
return(AUTH_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
passwd_verify(pw, pass, auth)
|
||||
struct passwd *pw;
|
||||
char *pass;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
char sav, *epass;
|
||||
size_t pw_len;
|
||||
int error;
|
||||
|
||||
pw_len = strlen(pw->pw_passwd);
|
||||
|
||||
#ifdef HAVE_GETAUTHUID
|
||||
/* Ultrix shadow passwords may use crypt16() */
|
||||
error = strcmp(pw->pw_passwd, (char *) crypt16(pass, pw->pw_passwd));
|
||||
if (!error)
|
||||
return(AUTH_SUCCESS);
|
||||
#endif /* HAVE_GETAUTHUID */
|
||||
|
||||
/*
|
||||
* Truncate to 8 chars if standard DES since not all crypt()'s do this.
|
||||
* If this turns out not to be safe we will have to use OS #ifdef's (sigh).
|
||||
*/
|
||||
sav = pass[8];
|
||||
if (pw_len == DESLEN || HAS_AGEINFO(pw->pw_passwd, pw_len))
|
||||
pass[8] = '\0';
|
||||
|
||||
/*
|
||||
* Normal UN*X password check.
|
||||
* HP-UX may add aging info (separated by a ',') at the end so
|
||||
* only compare the first DESLEN characters in that case.
|
||||
*/
|
||||
epass = (char *) crypt(pass, pw->pw_passwd);
|
||||
pass[8] = sav;
|
||||
if (HAS_AGEINFO(pw->pw_passwd, pw_len) && strlen(epass) == DESLEN)
|
||||
error = strncmp(pw->pw_passwd, epass, DESLEN);
|
||||
else
|
||||
error = strcmp(pw->pw_passwd, epass);
|
||||
|
||||
return(error ? AUTH_FAILURE : AUTH_SUCCESS);
|
||||
}
|
141
plugins/sudoers/auth/rfc1938.c
Normal file
141
plugins/sudoers/auth/rfc1938.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 1994-1996, 1998-2005
|
||||
* Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
|
||||
#if defined(HAVE_SKEY)
|
||||
# include <skey.h>
|
||||
# define RFC1938 skey
|
||||
# ifdef __NetBSD__
|
||||
# define rfc1938challenge(a,b,c,d) skeychallenge((a),(b),(c),(d))
|
||||
# else
|
||||
# define rfc1938challenge(a,b,c,d) skeychallenge((a),(b),(c))
|
||||
# endif
|
||||
# define rfc1938verify(a,b) skeyverify((a),(b))
|
||||
#elif defined(HAVE_OPIE)
|
||||
# include <opie.h>
|
||||
# define RFC1938 opie
|
||||
# define rfc1938challenge(a,b,c,d) opiechallenge((a),(b),(c))
|
||||
# define rfc1938verify(a,b) opieverify((a),(b))
|
||||
#endif
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
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, sizeof(challenge))) {
|
||||
if (IS_ONEANDONLY(auth)) {
|
||||
warningx("you do not exist in the %s database", 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_long_otp_prompt)
|
||||
(void) snprintf(new_prompt, np_size, "%s\n%s", challenge, orig_prompt);
|
||||
else
|
||||
(void) snprintf(new_prompt, np_size, "%.*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);
|
||||
}
|
98
plugins/sudoers/auth/secureware.c
Normal file
98
plugins/sudoers/auth/secureware.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2005 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_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"
|
||||
|
||||
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);
|
||||
}
|
108
plugins/sudoers/auth/securid.c
Normal file
108
plugins/sudoers/auth/securid.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
* 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.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
|
||||
#include <sdi_athd.h>
|
||||
#include <sdconf.h>
|
||||
#include <sdacmvls.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
union config_record configure;
|
||||
|
||||
int
|
||||
securid_init(pw, promptp, auth)
|
||||
struct passwd *pw;
|
||||
char **promptp;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
static struct SD_CLIENT sd_dat; /* SecurID data block */
|
||||
|
||||
auth->data = (void *) &sd_dat; /* For method-specific data */
|
||||
|
||||
if (creadcfg() == 0)
|
||||
return(AUTH_SUCCESS);
|
||||
else
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
int
|
||||
securid_setup(pw, promptp, auth)
|
||||
struct passwd *pw;
|
||||
char **promptp;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
struct SD_CLIENT *sd = (struct SD_CLIENT *) auth->data;
|
||||
|
||||
/* Re-initialize SecurID every time. */
|
||||
if (sd_init(sd) == 0) {
|
||||
/* The programmer's guide says username is 32 bytes */
|
||||
strlcpy(sd->username, pw->pw_name, 32);
|
||||
return(AUTH_SUCCESS);
|
||||
} else {
|
||||
warningx("unable to contact the SecurID server");
|
||||
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;
|
||||
int rval;
|
||||
|
||||
rval = sd_auth(sd);
|
||||
sd_close();
|
||||
if (rval == ACM_OK)
|
||||
return(AUTH_SUCCESS);
|
||||
else
|
||||
return(AUTH_FAILURE);
|
||||
}
|
232
plugins/sudoers/auth/securid5.c
Normal file
232
plugins/sudoers/auth/securid5.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* Copyright (c) 2002 Michael Stroucken <michael@stroucken.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
* 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.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
|
||||
/* Needed for SecurID v5.0 Authentication on UNIX */
|
||||
#define UNIX 1
|
||||
#include <acexport.h>
|
||||
#include <sdacmvls.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
/*
|
||||
* securid_init - Initialises communications with ACE server
|
||||
* Arguments in:
|
||||
* pw - UNUSED
|
||||
* promptp - UNUSED
|
||||
* auth - sudo authentication structure
|
||||
*
|
||||
* Results out:
|
||||
* auth - auth->data contains pointer to new SecurID handle
|
||||
* return code - Fatal if initialization unsuccessful, otherwise
|
||||
* success.
|
||||
*/
|
||||
int
|
||||
securid_init(pw, promptp, auth)
|
||||
struct passwd *pw;
|
||||
char **promptp;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
static SDI_HANDLE sd_dat; /* SecurID handle */
|
||||
|
||||
auth->data = (void *) &sd_dat; /* For method-specific data */
|
||||
|
||||
/* Start communications */
|
||||
if (AceInitialize() != SD_FALSE)
|
||||
return(AUTH_SUCCESS);
|
||||
|
||||
warningx("failed to initialise the ACE API library");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* securid_setup - Initialises a SecurID transaction and locks out other
|
||||
* ACE servers
|
||||
*
|
||||
* Arguments in:
|
||||
* pw - struct passwd for username
|
||||
* promptp - UNUSED
|
||||
* auth - sudo authentication structure for SecurID handle
|
||||
*
|
||||
* Results out:
|
||||
* return code - Success if transaction started correctly, fatal
|
||||
* otherwise
|
||||
*/
|
||||
int
|
||||
securid_setup(pw, promptp, auth)
|
||||
struct passwd *pw;
|
||||
char **promptp;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
|
||||
int retval;
|
||||
|
||||
/* Re-initialize SecurID every time. */
|
||||
if (SD_Init(sd) != ACM_OK) {
|
||||
warningx("unable to contact the SecurID server");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
|
||||
/* Lock new PIN code */
|
||||
retval = SD_Lock(*sd, pw->pw_name);
|
||||
|
||||
switch (retval) {
|
||||
case ACM_OK:
|
||||
warningx("User ID locked for SecurID Authentication");
|
||||
return(AUTH_SUCCESS);
|
||||
|
||||
case ACE_UNDEFINED_USERNAME:
|
||||
warningx("invalid username length for SecurID");
|
||||
return(AUTH_FATAL);
|
||||
|
||||
case ACE_ERR_INVALID_HANDLE:
|
||||
warningx("invalid Authentication Handle for SecurID");
|
||||
return(AUTH_FATAL);
|
||||
|
||||
case ACM_ACCESS_DENIED:
|
||||
warningx("SecurID communication failed");
|
||||
return(AUTH_FATAL);
|
||||
|
||||
default:
|
||||
warningx("unknown SecurID error");
|
||||
return(AUTH_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* securid_verify - Authenticates user and handles ACE responses
|
||||
*
|
||||
* Arguments in:
|
||||
* pw - struct passwd for username
|
||||
* pass - UNUSED
|
||||
* auth - sudo authentication structure for SecurID handle
|
||||
*
|
||||
* Results out:
|
||||
* return code - Success on successful authentication, failure on
|
||||
* incorrect authentication, fatal on errors
|
||||
*/
|
||||
int
|
||||
securid_verify(pw, pass, auth)
|
||||
struct passwd *pw;
|
||||
char *pass;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
|
||||
int rval;
|
||||
|
||||
pass = (char *) tgetpass("Enter your PASSCODE: ",
|
||||
def_passwd_timeout * 60, tgetpass_flags);
|
||||
|
||||
/* Have ACE verify password */
|
||||
switch (SD_Check(*sd, pass, pw->pw_name)) {
|
||||
case ACM_OK:
|
||||
rval = AUTH_SUCESS;
|
||||
break;
|
||||
|
||||
case ACE_UNDEFINED_PASSCODE:
|
||||
warningx("invalid passcode length for SecurID");
|
||||
rval = AUTH_FATAL;
|
||||
break;
|
||||
|
||||
case ACE_UNDEFINED_USERNAME:
|
||||
warningx("invalid username length for SecurID");
|
||||
rval = AUTH_FATAL;
|
||||
break;
|
||||
|
||||
case ACE_ERR_INVALID_HANDLE:
|
||||
warningx("invalid Authentication Handle for SecurID");
|
||||
rval = AUTH_FATAL;
|
||||
break;
|
||||
|
||||
case ACM_ACCESS_DENIED:
|
||||
rval = AUTH_FAILURE;
|
||||
break;
|
||||
|
||||
case ACM_NEXT_CODE_REQUIRED:
|
||||
/* Sometimes (when current token close to expire?)
|
||||
ACE challenges for the next token displayed
|
||||
(entered without the PIN) */
|
||||
pass = (char *) tgetpass("\
|
||||
!!! ATTENTION !!!\n\
|
||||
Wait for the token code to change, \n\
|
||||
then enter the new token code.\n", \
|
||||
def_passwd_timeout * 60, tgetpass_flags);
|
||||
|
||||
if (SD_Next(*sd, pass) == ACM_OK) {
|
||||
rval = AUTH_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
rval = AUTH_FAILURE;
|
||||
break;
|
||||
|
||||
case ACM_NEW_PIN_REQUIRED:
|
||||
/*
|
||||
* This user's SecurID has not been activated yet,
|
||||
* or the pin has been reset
|
||||
*/
|
||||
/* XXX - Is setting up a new PIN within sudo's scope? */
|
||||
SD_Pin(*sd, "");
|
||||
fprintf(stderr, "Your SecurID access has not yet been set up.\n");
|
||||
fprintf(stderr, "Please set up a PIN before you try to authenticate.\n");
|
||||
rval = AUTH_FATAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
warningx("unknown SecurID error");
|
||||
rval = AUTH_FATAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Free resources */
|
||||
SD_Close(*sd);
|
||||
|
||||
/* Return stored state to calling process */
|
||||
return(rval);
|
||||
}
|
137
plugins/sudoers/auth/sia.c
Normal file
137
plugins/sudoers/auth/sia.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
#include <siad.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
|
||||
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_passwd_timeout * 60)
|
||||
timeout = def_passwd_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;
|
||||
extern int Argc;
|
||||
extern char **Argv;
|
||||
|
||||
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);
|
||||
}
|
269
plugins/sudoers/auth/sudo_auth.c
Normal file
269
plugins/sudoers/auth/sudo_auth.c
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2008-2009 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_STRING_H
|
||||
# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
|
||||
# include <memory.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <pwd.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "sudo.h"
|
||||
#include "sudo_auth.h"
|
||||
#include "insults.h"
|
||||
|
||||
sudo_auth auth_switch[] = {
|
||||
#ifdef AUTH_STANDALONE
|
||||
AUTH_STANDALONE
|
||||
#else
|
||||
# ifndef WITHOUT_PASSWD
|
||||
AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL)
|
||||
# endif
|
||||
# if defined(HAVE_GETPRPWNAM) && !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)
|
||||
};
|
||||
|
||||
void
|
||||
verify_user(pw, prompt)
|
||||
struct passwd *pw;
|
||||
char *prompt;
|
||||
{
|
||||
int counter = def_passwd_tries + 1;
|
||||
int success = AUTH_FAILURE;
|
||||
int status;
|
||||
int flags;
|
||||
char *p;
|
||||
sudo_auth *auth;
|
||||
sigaction_t sa, osa;
|
||||
#ifdef HAVE_BSM_AUDIT
|
||||
extern char **NewArgv;
|
||||
#endif
|
||||
|
||||
/* Enable suspend during password entry. */
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
(void) sigaction(SIGTSTP, &sa, &osa);
|
||||
|
||||
/* Make sure we have at least one auth method. */
|
||||
if (auth_switch[0].name == NULL) {
|
||||
#ifdef HAVE_BSM_AUDIT
|
||||
audit_failure(NewArgv, "no authentication methods");
|
||||
#endif
|
||||
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)
|
||||
SET(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);
|
||||
|
||||
status = (auth->init)(pw, &prompt, auth);
|
||||
if (status == AUTH_FAILURE)
|
||||
CLR(auth->flags, FLAG_CONFIGURED);
|
||||
else if (status == AUTH_FATAL) { /* XXX log */
|
||||
#ifdef HAVE_BSM_AUDIT
|
||||
audit_failure(NewArgv, "authentication failure");
|
||||
#endif
|
||||
exit(1); /* assume error msg already printed */
|
||||
}
|
||||
|
||||
if (NEEDS_USER(auth))
|
||||
set_perms(PERM_ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
status = (auth->setup)(pw, &prompt, auth);
|
||||
if (status == AUTH_FAILURE)
|
||||
CLR(auth->flags, FLAG_CONFIGURED);
|
||||
else if (status == AUTH_FATAL) {/* XXX log */
|
||||
#ifdef HAVE_BSM_AUDIT
|
||||
audit_failure(NewArgv, "authentication failure");
|
||||
#endif
|
||||
exit(1); /* assume error msg already printed */
|
||||
}
|
||||
|
||||
if (NEEDS_USER(auth))
|
||||
set_perms(PERM_ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the password unless the auth function will do it for us */
|
||||
#ifdef AUTH_STANDALONE
|
||||
p = prompt;
|
||||
#else
|
||||
p = (char *) tgetpass(prompt, def_passwd_timeout * 60,
|
||||
tgetpass_flags);
|
||||
#endif /* AUTH_STANDALONE */
|
||||
|
||||
/* Call authentication functions. */
|
||||
for (auth = auth_switch; p && auth->name; auth++) {
|
||||
if (!IS_CONFIGURED(auth))
|
||||
continue;
|
||||
|
||||
if (NEEDS_USER(auth))
|
||||
set_perms(PERM_USER);
|
||||
|
||||
success = auth->status = (auth->verify)(pw, (char *)p, auth);
|
||||
|
||||
if (NEEDS_USER(auth))
|
||||
set_perms(PERM_ROOT);
|
||||
|
||||
if (auth->status != AUTH_FAILURE)
|
||||
goto cleanup;
|
||||
}
|
||||
#ifndef AUTH_STANDALONE
|
||||
if (p)
|
||||
zero_bytes(p, strlen(p));
|
||||
#endif
|
||||
if (!ISSET(tgetpass_flags, TGP_ASKPASS))
|
||||
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);
|
||||
|
||||
status = (auth->cleanup)(pw, auth);
|
||||
if (status == AUTH_FATAL) { /* XXX log */
|
||||
#ifdef HAVE_BSM_AUDIT
|
||||
audit_failure(NewArgv, "authentication failure");
|
||||
#endif
|
||||
exit(1); /* assume error msg already printed */
|
||||
}
|
||||
|
||||
if (NEEDS_USER(auth))
|
||||
set_perms(PERM_ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
switch (success) {
|
||||
case AUTH_SUCCESS:
|
||||
(void) sigaction(SIGTSTP, &osa, NULL);
|
||||
return;
|
||||
case AUTH_INTR:
|
||||
case AUTH_FAILURE:
|
||||
if (counter != def_passwd_tries) {
|
||||
if (def_mail_badpass || def_mail_always)
|
||||
flags = 0;
|
||||
else
|
||||
flags = NO_MAIL;
|
||||
#ifdef HAVE_BSM_AUDIT
|
||||
audit_failure(NewArgv, "authentication failure");
|
||||
#endif
|
||||
log_error(flags, "%d incorrect password attempt%s",
|
||||
def_passwd_tries - counter,
|
||||
(def_passwd_tries - counter == 1) ? "" : "s");
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case AUTH_FATAL:
|
||||
#ifdef HAVE_BSM_AUDIT
|
||||
audit_failure(NewArgv, "authentication failure");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
pass_warn(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
|
||||
#ifdef INSULT
|
||||
if (def_insults)
|
||||
(void) fprintf(fp, "%s\n", INSULT);
|
||||
else
|
||||
#endif
|
||||
(void) fprintf(fp, "%s\n", def_badpass_message);
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
113
plugins/sudoers/auth/sudo_auth.h
Normal file
113
plugins/sudoers/auth/sudo_auth.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007-2009 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SUDO_AUTH_H
|
||||
#define SUDO_AUTH_H
|
||||
|
||||
/* Auth function return values. */
|
||||
#define AUTH_SUCCESS 0
|
||||
#define AUTH_FAILURE 1
|
||||
#define AUTH_INTR 2
|
||||
#define AUTH_FATAL 3
|
||||
|
||||
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 the user, not 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));
|
||||
int aixauth_cleanup __P((struct passwd *pw, sudo_auth *auth));
|
||||
int bsdauth_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
|
||||
int bsdauth_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
|
||||
int bsdauth_cleanup __P((struct passwd *pw, sudo_auth *auth));
|
||||
|
||||
/* Prototypes for normal methods */
|
||||
int passwd_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
|
||||
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_SES_INIT)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "sia", \
|
||||
NULL, sia_setup, sia_verify, sia_cleanup)
|
||||
#elif defined(HAVE_AIXAUTH)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "aixauth", \
|
||||
NULL, NULL, aixauth_verify, aixauth_cleanup)
|
||||
#elif defined(HAVE_FWTK)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "fwtk", \
|
||||
fwtk_init, NULL, fwtk_verify, fwtk_cleanup)
|
||||
#elif defined(HAVE_BSD_AUTH_H)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "bsdauth", \
|
||||
bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup)
|
||||
#endif
|
||||
|
||||
#endif /* SUDO_AUTH_H */
|
Reference in New Issue
Block a user