Blob Blame History Raw
/*
 * Written by Cristian Gafton <gafton@redhat.com>
 */

#include "config.h"

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/types.h>

#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <pwd.h>
#include <getopt.h>

char *username = NULL;		/* username we are changing the password for */
char *password = NULL;		/* password we are changing the password to */

/* a dummy coversation function */
static int
dummy_conv(int num_msg,
	   const struct pam_message **msg,
	   struct pam_response **resp, void *appdata_ptr)
{
	int i;
	struct pam_response *response = NULL;

	(void)appdata_ptr;

	response = malloc(sizeof(struct pam_response) * num_msg);

	if (response == (struct pam_response *) 0)
		return PAM_CONV_ERR;

	for (i = 0; i < num_msg; i++) {
		response[i].resp_retcode = PAM_SUCCESS;

		switch (msg[i]->msg_style) {
		case PAM_PROMPT_ECHO_ON:
			response[i].resp = username;
			break;

		case PAM_PROMPT_ECHO_OFF:
			response[i].resp = password;
			break;

		case PAM_TEXT_INFO:
		case PAM_ERROR_MSG:
			/* ignore it, but pam still wants a NULL response... */
			response[i].resp = NULL;
			break;

		default:
			/* Must be an error of some sort... */
			free(response);
			return PAM_CONV_ERR;
		}
	}

	*resp = response;
	return PAM_SUCCESS;
}


/* conversation function & corresponding structure */
static struct pam_conv conv = {
	&dummy_conv,
	NULL
};

int
main(int argc, char *const argv[])
{
	int retval;
	pam_handle_t *pamh = NULL;

	/* XXX; expand me:
	 *
	 * here you should obtains somehow the username and password and
	 * set the global variables
	 */
	(void)argc;
	(void)argv;
	assert(username != NULL);
	assert(password != NULL);

	retval = pam_start("passwd", username, &conv, &pamh);
	while (retval == PAM_SUCCESS) {	/* use loop to avoid goto... */

		retval = pam_chauthtok(pamh, 0);
		if (retval != PAM_SUCCESS)
			break;
		/* all done */
		retval = pam_end(pamh, PAM_SUCCESS);
		if (retval != PAM_SUCCESS)
			break;
		/* quit gracefully */
		exit(0);
	}

	if (retval != PAM_SUCCESS)
		fprintf(stderr, "changing password: %s\n",
			pam_strerror(pamh, retval));

	if (pamh != NULL) {
		(void) pam_end(pamh, PAM_SUCCESS);
		pamh = NULL;
	}

	exit(1);
}