diff --git a/plugins/sudoers/auth/API b/plugins/sudoers/auth/API index fd183fe84..24bd51086 100644 --- a/plugins/sudoers/auth/API +++ b/plugins/sudoers/auth/API @@ -7,15 +7,17 @@ Purpose: to provide a simple API for authentication methods that The sudo_auth struct looks like this: typedef struct sudo_auth { - short flags; /* various flags, see below */ - short status; /* status from verify routine */ + int flags; /* various flags, see below */ + int 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)); + int (*init)(struct passwd *pw, char **prompt, sudo_auth *auth); + int (*setup)(struct passwd *pw, char **prompt, sudo_auth *auth); + int (*verify)(struct passwd *pw, char *p, sudo_auth *auth); + int (*cleanup)(struct passwd *pw, sudo_auth *auth); + int (*begin_session)(struct passwd *pw, sudo_auth *auth); + int (*end_session)(sudo_auth *auth); } sudo_auth; The variables in the struct are as follows: @@ -34,10 +36,11 @@ 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_DISABLED Set if an "init" or "setup" function fails. + + FLAG_STANDALONE If set, this indicates that the method must + be the only auth method configured, and that + it will prompt for the password itself. FLAG_ONEANDONLY If set, this indicates that the method is the only one in use. Can be used by auth functions @@ -97,32 +100,23 @@ 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: +Add the method to the ``auth_switch'' in sudo_auth.c. Note that +standalone methods must go first. If ``fooauth'' is a normal auth +method, its entry would look like: -#elif defined(HAVE_FOOAUTH) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "foo", \ - foo_init, foo_setup, foo_verify, foo_cleanup) +#ifdef HAVE_FOOAUTH +AUTH_ENTRY("foo", 0, foo_init, foo_setup, foo_verify, + foo_cleanup, foo_begin_session, foo_end_session) +#endif -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. +If this is a standalone method, it would be: -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("foo", FLAG_STANDALONE, foo_init, foo_setup, foo_verify, + foo_cleanup, foo_begin_session, foo_end_session) +#endif -# 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. +If the method needs to run as the user, not root, add FLAG_USER to +the second argument in the AUTH_ENTRY line. If you don't have an +init/setup/cleanup/begin/end routine, just use a NULL for that +field. diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c index e674ce4a0..427145358 100644 --- a/plugins/sudoers/auth/sudo_auth.c +++ b/plugins/sudoers/auth/sudo_auth.c @@ -52,36 +52,53 @@ #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, NULL, NULL) -# endif -# if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD) - AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL, NULL, NULL) -# endif -# ifdef HAVE_AFS - AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL, NULL, NULL) -# endif -# ifdef HAVE_DCE - AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL, NULL, NULL) -# endif -# ifdef HAVE_KERB4 - AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL) -# endif -# ifdef HAVE_KERB5 - AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL) -# endif -# ifdef HAVE_SKEY - AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL) -# endif -# ifdef HAVE_OPIE - AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL) -# endif -#endif /* AUTH_STANDALONE */ - AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL) +static sudo_auth auth_switch[] = { +/* Standalone entries first */ +#ifdef HAVE_PAM + AUTH_ENTRY("pam", FLAG_STANDALONE, pam_init, NULL, pam_verify, pam_cleanup, pam_begin_session, pam_end_session) +#endif +#ifdef HAVE_SECURID + AUTH_ENTRY("SecurId", FLAG_STANDALONE, securid_init, securid_setup, securid_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_SIA_SES_INIT + AUTH_ENTRY("sia", FLAG_STANDALONE, NULL, sia_setup, sia_verify, sia_cleanup, NULL, NULL) +#endif +#ifdef HAVE_AIXAUTH + AUTH_ENTRY("aixauth", FLAG_STANDALONE, NULL, NULL, aixauth_verify, aixauth_cleanup, NULL, NULL) +#endif +#ifdef HAVE_FWTK + AUTH_ENTRY("fwtk", FLAG_STANDALONE, fwtk_init, NULL, fwtk_verify, fwtk_cleanup, NULL, NULL) +#endif +#ifdef HAVE_BSD_AUTH_H + AUTH_ENTRY("bsdauth", FLAG_STANDALONE, bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup, NULL, NULL) +#endif + +/* Non-standalone entries */ +#ifndef WITHOUT_PASSWD + AUTH_ENTRY("passwd", 0, passwd_init, NULL, passwd_verify, NULL, NULL, NULL) +#endif +#if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD) + AUTH_ENTRY("secureware", 0, secureware_init, NULL, secureware_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_AFS + AUTH_ENTRY("afs", 0, NULL, NULL, afs_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_DCE + AUTH_ENTRY("dce", 0, NULL, NULL, dce_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_KERB4 + AUTH_ENTRY("kerb4", 0, kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_KERB5 + AUTH_ENTRY("kerb5", 0, kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL) +#endif +#ifdef HAVE_SKEY + AUTH_ENTRY("S/Key", 0, NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_OPIE + AUTH_ENTRY("OPIE", 0, NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL) +#endif + AUTH_ENTRY(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL) }; extern char **NewArgv; /* XXX - for auditing */ @@ -93,7 +110,7 @@ verify_user(struct passwd *pw, char *prompt) { int counter = def_passwd_tries + 1; int success = AUTH_FAILURE; - int flags, status, rval; + int flags, status, standalone, rval; char *p; sudo_auth *auth; sigaction_t sa, osa; @@ -114,19 +131,28 @@ verify_user(struct passwd *pw, char *prompt) return -1; } + /* Make sure we haven't mixed standalone and shared auth methods. */ + standalone = IS_STANDALONE(&auth_switch[0]); + if (standalone && auth_switch[1].name != NULL) { + audit_failure(NewArgv, "invalid authentication methods"); + log_error(0, "Invalid authentication methods compiled into sudo! " + "You cannot mix standalone and non-standalone authentication."); + return -1; + } + /* 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 (auth->init && !IS_DISABLED(auth)) { if (NEEDS_USER(auth)) set_perms(PERM_USER); status = (auth->init)(pw, &prompt, auth); if (status == AUTH_FAILURE) - CLR(auth->flags, FLAG_CONFIGURED); + SET(auth->flags, FLAG_DISABLED); else if (status == AUTH_FATAL) { /* XXX log */ audit_failure(NewArgv, "authentication failure"); return -1; /* assume error msg already printed */ @@ -140,13 +166,13 @@ verify_user(struct passwd *pw, char *prompt) 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 (auth->setup && !IS_DISABLED(auth)) { if (NEEDS_USER(auth)) set_perms(PERM_USER); status = (auth->setup)(pw, &prompt, auth); if (status == AUTH_FAILURE) - CLR(auth->flags, FLAG_CONFIGURED); + SET(auth->flags, FLAG_DISABLED); else if (status == AUTH_FATAL) {/* XXX log */ audit_failure(NewArgv, "authentication failure"); return -1; /* assume error msg already printed */ @@ -158,21 +184,20 @@ verify_user(struct passwd *pw, char *prompt) } /* Get the password unless the auth function will do it for us */ -#ifdef AUTH_STANDALONE - p = prompt; -#else - p = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF); -#endif /* AUTH_STANDALONE */ + if (standalone) + p = prompt; + else + p = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF); /* Call authentication functions. */ for (auth = auth_switch; p && auth->name; auth++) { - if (!IS_CONFIGURED(auth)) + if (IS_DISABLED(auth)) continue; if (NEEDS_USER(auth)) set_perms(PERM_USER); - success = auth->status = (auth->verify)(pw, (char *)p, auth); + success = auth->status = (auth->verify)(pw, p, auth); if (NEEDS_USER(auth)) restore_perms(); @@ -180,17 +205,15 @@ verify_user(struct passwd *pw, char *prompt) if (auth->status != AUTH_FAILURE) goto cleanup; } -#ifndef AUTH_STANDALONE - if (p) + if (!standalone && p != NULL) zero_bytes(p, strlen(p)); -#endif pass_warn(); } cleanup: /* Call cleanup routines. */ for (auth = auth_switch; auth->name; auth++) { - if (auth->cleanup && IS_CONFIGURED(auth)) { + if (auth->cleanup && !IS_DISABLED(auth)) { if (NEEDS_USER(auth)) set_perms(PERM_USER); @@ -240,7 +263,7 @@ int auth_begin_session(struct passwd *pw) int status; for (auth = auth_switch; auth->name; auth++) { - if (auth->begin_session && IS_CONFIGURED(auth)) { + if (auth->begin_session && !IS_DISABLED(auth)) { status = (auth->begin_session)(pw, auth); if (status == AUTH_FATAL) { /* XXX log */ audit_failure(NewArgv, "authentication failure"); @@ -257,7 +280,7 @@ int auth_end_session(void) int status; for (auth = auth_switch; auth->name; auth++) { - if (auth->end_session && IS_CONFIGURED(auth)) { + if (auth->end_session && !IS_DISABLED(auth)) { status = (auth->end_session)(auth); if (status == AUTH_FATAL) { /* XXX log */ return -1; /* assume error msg already printed */ diff --git a/plugins/sudoers/auth/sudo_auth.h b/plugins/sudoers/auth/sudo_auth.h index ef1bad2e7..a2034ea2a 100644 --- a/plugins/sudoers/auth/sudo_auth.h +++ b/plugins/sudoers/auth/sudo_auth.h @@ -24,8 +24,8 @@ #define AUTH_FATAL 3 typedef struct sudo_auth { - short flags; /* various flags, see below */ - short status; /* status from verify routine */ + int flags; /* various flags, see below */ + int status; /* status from verify routine */ char *name; /* name of the method as a string */ void *data; /* method-specific data pointer */ int (*init)(struct passwd *pw, char **prompt, struct sudo_auth *auth); @@ -37,14 +37,15 @@ typedef struct sudo_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 */ +#define FLAG_DISABLED 0x02 /* method disabled */ +#define FLAG_STANDALONE 0x04 /* standalone auth method */ +#define FLAG_ONEANDONLY 0x08 /* 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_DISABLED(x) ((x)->flags & FLAG_DISABLED) +#define IS_STANDALONE(x) ((x)->flags & FLAG_STANDALONE) #define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY) /* Like tgetpass() but uses conversation function */ @@ -89,35 +90,8 @@ int securid_init(struct passwd *pw, char **prompt, sudo_auth *auth); int securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth); int securid_verify(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, b, e) \ - { (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c , b, e }, - -/* Some methods cannot (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, pam_begin_session, pam_end_session) -#elif defined(HAVE_SECURID) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "SecurId", \ - securid_init, securid_setup, securid_verify, NULL, NULL, NULL) -#elif defined(HAVE_SIA_SES_INIT) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "sia", \ - NULL, sia_setup, sia_verify, sia_cleanup, NULL, NULL) -#elif defined(HAVE_AIXAUTH) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "aixauth", \ - NULL, NULL, aixauth_verify, aixauth_cleanup, NULL, NULL) -#elif defined(HAVE_FWTK) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "fwtk", \ - fwtk_init, NULL, fwtk_verify, fwtk_cleanup, NULL, NULL) -#elif defined(HAVE_BSD_AUTH_H) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "bsdauth", \ - bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup, NULL, NULL) -#endif +/* Fields: name, flags, init, setup, verify, cleanup, begin_sess, end_sess */ +#define AUTH_ENTRY(n, f, i, s, v, c, b, e) \ + { (f), AUTH_FAILURE, (n), NULL, (i), (s), (v), (c) , (b), (e) }, #endif /* SUDO_AUTH_H */