예제 #1
0
파일: yk_chkpwd.c 프로젝트: firnsy/yubipam
// Main
int main(int argc, char *argv[]) {
    char pass[MAXPASS + 1];
    int npass;
    int retval = YK_FAILURE;
    int debug = 0;
    int ch;
    char *user = NULL;

    /*
     * Catch or ignore as many signal as possible.
     */
    setup_signals();

    /* loop through each command line var and process it */
    while((ch = getopt(argc, argv, "d")) != -1) {
        switch(ch) {
            case 'd': /* Set debug mode on */
                debug = 1;
                break;
        }
    }
    
    /* there should be at least one left over argument */
    if (optind < argc) {
        /* grab the first additional argument as the user name */
        user = strdup(argv[optind]);
    }

    /*
     * we establish that this program is running with non-tty stdin.
     * this is to discourage casual use. It does *NOT* prevent an
     * intruder from repeatadly running this program to determine the
     * OTP/passcode of the current user (brute force attack, but one for
     * which the attacker must already have gained access to the user's
     * account).
     */
    if (isatty(STDIN_FILENO) || user == NULL ) {
        syslog(LOG_AUTH
            ,"inappropriate use of Unix helper binary [UID=%d]"
            ,getuid());
        fprintf(stderr
            ,"This binary is not designed for running in this way\n"
             "-- the system administrator has been informed\n");
        sleep(10);    // this should discourage/annoy the user
        return YK_FAILURE;
    }

    /*
     * Determine what the current user's name is.
     * On a SELinux enabled system with a strict policy leaving the
     * existing check prevents shadow password authentication from working.
     * We must thus skip the check if the real uid is 0.
     */
    if (getuid() != 0) {
        /* if the caller specifies the username, verify that user
         matches it */
        if (strcmp(user, getuidname(getuid()))) {
            syslog(LOG_AUTH
                ,"mismatch of %s|%s", user, getuidname(getuid()));
            free(user);
            return YK_FAILURE;
        }
    }

    /* read the OTP/passcode from stdin (a pipe from the pam_yubikey module) */
    npass = read(STDIN_FILENO, pass, MAXPASS);

    if (npass < 0) {    /* is it a valid OTP/passcode? */
        syslog(LOG_DEBUG, "no OTP/passcode supplied");
    } else if (npass >= MAXPASS) {
        syslog(LOG_DEBUG, "OTP/passcode too long");
    } else {
        pass[npass] = '\0';    /* NUL terminate */
        retval = _yubi_verify_otp_passcode(user, pass, debug, 1);
    }

    memset(pass, '\0', MAXPASS);    /* clear memory of the OTP/passcode */

    /* return pass or fail */
    if ((retval != YK_SUCCESS) && (retval != YK_PASSCODE)) {
        if (debug)
            syslog(LOG_AUTH, "OTP/passcode check failed for user (%s)", user);
        free(user);
        return YK_FAILURE;
    }
    
    free(user);
    return retval;
}
예제 #2
0
int
main(int argc, char *argv[])
{
	const char *program_name;
	char	*service, *user;
	int	fd;
	uid_t	uid;

	uid = getuid();

	/*
	 * Make sure standard file descriptors are connected.
	 */
	while ((fd = open("/dev/null", O_RDWR)) <= 2)
		;
	close(fd);

	/*
	 * Get the program name
	 */
	if (argc == 0)
		program_name = "hawk_chkpwd";
	else if ((program_name = strrchr(argv[0], '/')) != NULL)
		program_name++;
	else
		program_name = argv[0];

	/*
	 * Catch or ignore as many signal as possible.
	 */
	setup_signals();

	/*
	 * Check argument list
	 */
	if (argc != 3) {
		_log_err(LOG_NOTICE, "Bad number of arguments (%d)", argc);
		return UNIX_FAILED;
	}

	/*
	 * Get the service name and do some sanity checks on it
	 */
	service = argv[1];
	if (!sane_pam_service(service)) {
		_log_err(LOG_ERR, "Illegal service name '%s'", service);
		return UNIX_FAILED;
	}

	/*
	 * Discourage users messing around (fat chance)
	 */
	if (isatty(STDIN_FILENO) && uid != 0) {
		_log_err(LOG_NOTICE,
			"Inappropriate use of Unix helper binary [UID=%d]",
			 uid);
		fprintf(stderr,
			"This binary is not designed for running in this way\n"
			"-- the system administrator has been informed\n");
		sleep(10);	/* this should discourage/annoy the user */
		return UNIX_FAILED;
	}

	/*
	 * determine the caller's user name
	 */
	user = getuidname(uid);
	if (strcmp(user, argv[2])) {
		/* Discourage use of this program as a
		 * password cracker */
		if (uid != 0 && strcmp(user, HACLUSTER))
			sleep(5);
		user = argv[2];
	}
	if (!in_haclient_grp(user)) {
		_log_err(LOG_NOTICE,
			"Failed to authenticate user '%s' (not in group '%s')",
			user, HACLIENT);
		return UNIX_FAILED;
	}
	return _authenticate(service, user);
}
예제 #3
0
int main(int argc, char *argv[])
{
	char pass[MAXPASS + 1];
	char option[8];
	int npass, opt;
	int force_failure = 0;
	int retval = UNIX_FAILED;
	char *user;

	/*
	 * Catch or ignore as many signal as possible.
	 */
	setup_signals();

	/*
	 * we establish that this program is running with non-tty stdin.
	 * this is to discourage casual use. It does *NOT* prevent an
	 * intruder from repeatadly running this program to determine the
	 * password of the current user (brute force attack, but one for
	 * which the attacker must already have gained access to the user's
	 * account).
	 */

	if (isatty(STDIN_FILENO)) {

		_log_err(LOG_NOTICE
		      ,"inappropriate use of Unix helper binary [UID=%d]"
			 ,getuid());
		fprintf(stderr
		 ,"This binary is not designed for running in this way\n"
		      "-- the system administrator has been informed\n");
		sleep(10);	/* this should discourage/annoy the user */
		return UNIX_FAILED;
	}

	/*
	 * determine the current user's name is
	 */
	user = getuidname(getuid());
	if (argc == 2) {
	    /* if the caller specifies the username, verify that user
	       matches it */
	    if (strcmp(user, argv[1])) {
		force_failure = 1;
	    }
	}

	/* read the nollok/nonull option */

	npass = read(STDIN_FILENO, option, 8);

	if (npass < 0) {
		_log_err(LOG_DEBUG, "no option supplied");
		return UNIX_FAILED;
	} else {
		option[7] = '\0';
		if (strncmp(option, "nullok", 8) == 0)
			opt = 1;
		else
			opt = 0;
	}

	/* read the password from stdin (a pipe from the pam_unix module) */

	npass = read(STDIN_FILENO, pass, MAXPASS);

	if (npass < 0) {	/* is it a valid password? */

		_log_err(LOG_DEBUG, "no password supplied");

	} else if (npass >= MAXPASS) {

		_log_err(LOG_DEBUG, "password too long");

	} else {
		if (npass == 0) {
			/* the password is NULL */

			retval = _unix_verify_password(user, NULL, opt);

		} else {
			/* does pass agree with the official one? */

			pass[npass] = '\0';	/* NUL terminate */
			retval = _unix_verify_password(user, pass, opt);

		}
	}

	memset(pass, '\0', MAXPASS);	/* clear memory of the password */

	/* return pass or fail */

	if ((retval != UNIX_PASSED) || force_failure) {
	    return UNIX_FAILED;
	} else {
	    return UNIX_PASSED;
	}
}
예제 #4
0
int main(int argc, char *argv[])
{
    char pass[MAXPASS + 1];
    char *option;
    int npass, nullok;
    int blankpass = 0;
    int retval = PAM_AUTH_ERR;
    char *user;
    char *passwords[] = { pass };

    /*
     * Catch or ignore as many signal as possible.
     */
    setup_signals();

    /*
     * we establish that this program is running with non-tty stdin.
     * this is to discourage casual use. It does *NOT* prevent an
     * intruder from repeatadly running this program to determine the
     * password of the current user (brute force attack, but one for
     * which the attacker must already have gained access to the user's
     * account).
     */

    if (isatty(STDIN_FILENO) || argc != 3 ) {
        helper_log_err(LOG_NOTICE
                       ,"inappropriate use of Unix helper binary [UID=%d]"
                       ,getuid());
#ifdef HAVE_LIBAUDIT
        _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR);
#endif
        fprintf(stderr
                ,"This binary is not designed for running in this way\n"
                "-- the system administrator has been informed\n");
        sleep(10);	/* this should discourage/annoy the user */
        return PAM_SYSTEM_ERR;
    }

    /*
     * Determine what the current user's name is.
     * We must thus skip the check if the real uid is 0.
     */
    if (getuid() == 0) {
        user=argv[1];
    }
    else {
        user = getuidname(getuid());
        /* if the caller specifies the username, verify that user
           matches it */
        if (strcmp(user, argv[1])) {
            user = argv[1];
            /* no match -> permanently change to the real user and proceed */
            if (setuid(getuid()) != 0)
                return PAM_AUTH_ERR;
        }
    }

    option=argv[2];

    if (strcmp(option, "chkexpiry") == 0)
        /* Check account information from the shadow file */
        return _check_expiry(argv[1]);
    /* read the nullok/nonull option */
    else if (strcmp(option, "nullok") == 0)
        nullok = 1;
    else if (strcmp(option, "nonull") == 0)
        nullok = 0;
    else {
#ifdef HAVE_LIBAUDIT
        _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR);
#endif
        return PAM_SYSTEM_ERR;
    }
    /* read the password from stdin (a pipe from the pam_unix module) */

    npass = read_passwords(STDIN_FILENO, 1, passwords);

    if (npass != 1) {	/* is it a valid password? */
        helper_log_err(LOG_DEBUG, "no password supplied");
        *pass = '******';
    }

    if (*pass == '\0') {
        blankpass = 1;
    }

    retval = helper_verify_password(user, pass, nullok);

    memset(pass, '\0', MAXPASS);	/* clear memory of the password */

    /* return pass or fail */

    if (retval != PAM_SUCCESS) {
        if (!nullok || !blankpass) {
            /* no need to log blank pass test */
#ifdef HAVE_LIBAUDIT
            if (getuid() != 0)
                _audit_log(AUDIT_USER_AUTH, user, PAM_AUTH_ERR);
#endif
            helper_log_err(LOG_NOTICE, "password check failed for user (%s)", user);
        }
        return PAM_AUTH_ERR;
    } else {
        if (getuid() != 0) {
#ifdef HAVE_LIBAUDIT
            return _audit_log(AUDIT_USER_AUTH, user, PAM_SUCCESS);
#else
            return PAM_SUCCESS;
#endif
        }
        return PAM_SUCCESS;
    }
}