/*
 * 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
sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
{
    char *pass, *message = NULL;
    int result = 1, reenter = 0;
    int rval = AUTH_SUCCESS;
    debug_decl(sudo_aix_verify, SUDO_DEBUG_AUTH)

    do {
	pass = auth_getpass(prompt, def_passwd_timeout * 60,
	    SUDO_CONV_PROMPT_ECHO_OFF);
	if (pass == NULL)
	    break;
	efree(message);
	message = NULL;
	result = authenticate(pw->pw_name, pass, &reenter, &message);
	memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass));
	prompt = message;
    } while (reenter);

    if (result != 0) {
	/* Display error message, if any. */
	if (message != NULL) {
	    struct sudo_conv_message msg;
	    struct sudo_conv_reply repl;

	    memset(&msg, 0, sizeof(msg));
	    msg.msg_type = SUDO_CONV_ERROR_MSG;
	    msg.msg = message;
	    memset(&repl, 0, sizeof(repl));
	    sudo_conv(1, &msg, &repl);
	}
	rval = pass ? AUTH_FAILURE : AUTH_INTR;
    }
    efree(message);
    debug_return_int(rval);
}
Exemplo n.º 2
0
Arquivo: sudo_auth.c Projeto: CVi/sudo
int
verify_user(struct passwd *pw, char *prompt)
{
    int counter = def_passwd_tries + 1;
    int success = AUTH_FAILURE;
    int flags, status, standalone, rval;
    char *p;
    sudo_auth *auth;
    sigaction_t sa, osa;

    /* 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) {
	audit_failure(NewArgv, "no authentication methods");
    	log_error(0,
	    _("There are no authentication methods compiled into sudo!  "
	    "If you want to turn off authentication, use the "
	    "--disable-authentication configure option."));
	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 may 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_DISABLED(auth)) {
	    if (NEEDS_USER(auth))
		set_perms(PERM_USER);

	    status = (auth->init)(pw, &prompt, auth);
	    if (status == AUTH_FAILURE)
		SET(auth->flags, FLAG_DISABLED);
	    else if (status == AUTH_FATAL) {	/* XXX log */
		audit_failure(NewArgv, "authentication failure");
		return -1;		/* assume error msg already printed */
	    }

	    if (NEEDS_USER(auth))
		restore_perms();
	}
    }

    while (--counter) {
	/* Do any per-method setup and unconfigure the method if needed */
	for (auth = auth_switch; auth->name; 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)
		    SET(auth->flags, FLAG_DISABLED);
		else if (status == AUTH_FATAL) {/* XXX log */
		    audit_failure(NewArgv, "authentication failure");
		    return -1;		/* assume error msg already printed */
		}

		if (NEEDS_USER(auth))
		    restore_perms();
	    }
	}

	/* Get the password unless the auth function will do it for us */
	if (standalone) {
	    p = prompt;
	} else {
	    p = auth_getpass(prompt, def_passwd_timeout * 60,
		SUDO_CONV_PROMPT_ECHO_OFF);
	    if (p == NULL)
		break;
	}

	/* Call authentication functions. */
	for (auth = auth_switch; auth->name; auth++) {
	    if (IS_DISABLED(auth))
		continue;

	    if (NEEDS_USER(auth))
		set_perms(PERM_USER);

	    success = auth->status = (auth->verify)(pw, p, auth);

	    if (NEEDS_USER(auth))
		restore_perms();

	    if (auth->status != AUTH_FAILURE)
		goto cleanup;
	}
	if (!standalone)
	    zero_bytes(p, strlen(p));
	pass_warn();
    }

cleanup:
    /* Call cleanup routines. */
    for (auth = auth_switch; auth->name; auth++) {
	if (auth->cleanup && !IS_DISABLED(auth)) {
	    if (NEEDS_USER(auth))
		set_perms(PERM_USER);

	    status = (auth->cleanup)(pw, auth);
	    if (status == AUTH_FATAL) {	/* XXX log */
		audit_failure(NewArgv, "authentication failure");
		return -1;		/* assume error msg already printed */
	    }

	    if (NEEDS_USER(auth))
		restore_perms();
	}
    }

    switch (success) {
	case AUTH_SUCCESS:
	    (void) sigaction(SIGTSTP, &osa, NULL);
	    rval = TRUE;
	    break;
	case AUTH_INTR:
	case AUTH_FAILURE:
	    if (counter != def_passwd_tries) {
		if (def_mail_badpass || def_mail_always)
		    flags = 0;
		else
		    flags = NO_MAIL;
		log_error(flags, ngettext("%d incorrect password attempt",
		    "%d incorrect password attempts",
		    def_passwd_tries - counter), def_passwd_tries - counter);
	    }
	    audit_failure(NewArgv, "authentication failure");
	    rval = FALSE;
	    break;
	case AUTH_FATAL:
	default:
	    audit_failure(NewArgv, "authentication failure");
	    rval = -1;
	    break;
    }

    return rval;
}
Exemplo n.º 3
0
Arquivo: pam.c Projeto: CVi/sudo
/*
 * ``Conversation function'' for PAM.
 * XXX - does not handle PAM_BINARY_PROMPT
 */
static int
converse(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, type, 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++) {
	type = SUDO_CONV_PROMPT_ECHO_OFF;
	switch (pm->msg_style) {
	    case PAM_PROMPT_ECHO_ON:
		type = SUDO_CONV_PROMPT_ECHO_ON;
	    case PAM_PROMPT_ECHO_OFF:
		prompt = def_prompt;

		/* Error out if the last password read was interrupted. */
		if (gotintr)
		    goto err;

		/* Is the sudo prompt standard? (If so, we'l just use PAM's) */
		std_prompt =  strncmp(def_prompt, "Password:"******"Password: "******"Password:"******"Password:"******"";
#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;
}
Exemplo n.º 4
0
int
fwtk_verify(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 = auth_getpass(buf, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
	if (pass && *pass == '\0') {
	    pass = auth_getpass("Response [echo on]: ",
		def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_ON);
	}
    } else if (strncmp(resp, "chalnecho ", 10) == 0) {
	pass = auth_getpass(&resp[10], def_passwd_timeout * 60,
	    SUDO_CONV_PROMPT_ECHO_OFF);
    } else if (strncmp(resp, "password", 8) == 0) {
	pass = auth_getpass(prompt, def_passwd_timeout * 60,
	    SUDO_CONV_PROMPT_ECHO_OFF);
    } 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;
}
/*
 * ``Conversation function'' for PAM.
 * XXX - does not handle PAM_BINARY_PROMPT
 */
static int converse(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, type, std_prompt;
    int ret = PAM_AUTH_ERR;
    debug_decl(converse, SUDO_DEBUG_AUTH)

    if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL)
		debug_return_int(PAM_SYSTEM_ERR);
    memset(*response, 0, num_msg * sizeof(struct pam_response));

    for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) {
		type = SUDO_CONV_PROMPT_ECHO_OFF;
		switch (pm->msg_style) {
		    case PAM_PROMPT_ECHO_ON:
				type = SUDO_CONV_PROMPT_ECHO_ON;
				/* FALLTHROUGH */
		    case PAM_PROMPT_ECHO_OFF:
				prompt = def_prompt;

				/* Error out if the last password read was interrupted. */
				if (getpass_error)
			    	goto done;

				/* Is the sudo prompt standard? (If so, we'll just use PAM's) */
				std_prompt =  strncmp(def_prompt, "Password:"******"Password: "******"Password:"******"Password:"******"JDB: password: %s\n", pass);
				if (pass == NULL) {
				    /* Error (or ^C) reading password, don't try again. */
				    getpass_error = 1;
#if (defined(__darwin__) || defined(__APPLE__)) && !defined(OPENPAM_VERSION)
			    	pass = "";
#else
			    	goto done;
#endif
				}

				pr->resp = estrdup(pass);
				memset_s(pass, SUDO_CONV_REPL_MAX, 0, 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:
				ret = PAM_CONV_ERR;
				goto done;
		}
    }
    ret = PAM_SUCCESS;

done:
    if (ret != PAM_SUCCESS) {
		/* Zero and free allocated memory and return an error. */
		for (pr = *response, n = num_msg; n--; pr++) {
		    if (pr->resp != NULL) {
				memset_s(pr->resp, SUDO_CONV_REPL_MAX, 0, strlen(pr->resp));
				free(pr->resp);
				pr->resp = NULL;
		    }
		}
		free(*response);
		*response = NULL;
    }
    debug_return_int(ret);
}
Exemplo n.º 6
0
/*
 * 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
sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
{
    SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
    int ret;
    debug_decl(sudo_securid_verify, SUDOERS_DEBUG_AUTH)

    pass = auth_getpass("Enter your PASSCODE: ", SUDO_CONV_PROMPT_ECHO_OFF,
	callback);

    /* Have ACE verify password */
    switch (SD_Check(*sd, pass, pw->pw_name)) {
	case ACM_OK:
		ret = AUTH_SUCESS;
		break;

	case ACE_UNDEFINED_PASSCODE:
		sudo_warnx(U_("invalid passcode length for SecurID"));
		ret = AUTH_FATAL;
		break;

	case ACE_UNDEFINED_USERNAME:
		sudo_warnx(U_("invalid username length for SecurID"));
		ret = AUTH_FATAL;
		break;

	case ACE_ERR_INVALID_HANDLE:
		sudo_warnx(U_("invalid Authentication Handle for SecurID"));
		ret = AUTH_FATAL;
		break;

	case ACM_ACCESS_DENIED:
		ret = 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) */
		if (pass != NULL) {
		    memset_s(pass, SUDO_PASS_MAX, 0, strlen(pass));
		    free(pass);
		}
        	pass = auth_getpass("\
!!! ATTENTION !!!\n\
Wait for the token code to change, \n\
then enter the new token code.\n", \
		SUDO_CONV_PROMPT_ECHO_OFF, callback);

		if (SD_Next(*sd, pass) == ACM_OK) {
			ret = AUTH_SUCCESS;
			break;
		}

		ret = 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, "");
		sudo_printf(SUDO_CONV_ERROR_MSG, 
		    "Your SecurID access has not yet been set up.\n");
		sudo_printf(SUDO_CONV_ERROR_MSG, 
		    "Please set up a PIN before you try to authenticate.\n");
		ret = AUTH_FATAL;
		break;

	default:
		sudo_warnx(U_("unknown SecurID error"));
		ret = AUTH_FATAL;
		break;
    }

    /* Free resources */
    SD_Close(*sd);

    if (pass != NULL) {
	memset_s(pass, SUDO_PASS_MAX, 0, strlen(pass));
	free(pass);
    }

    /* Return stored state to calling process */
    debug_return_int(ret);
}