/*
 * Small tool to print the pam prompts for a particular service.
 *
 * This code leaks memory.
 *
 * By Ted Percival <ted@midg3t.net>, 2007-01-22.
 *
 * Copyright © 2007, Quest Software
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Quest Software nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY QUEST SOFTWARE ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL QUEST SOFTWARE BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, 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.
 *
 */

#include <security/pam_appl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int conv(int num_msg, const struct pam_message **msg,
		struct pam_response **resp, void *appdata_ptr);

int main(int argc, char *argv[]) {
	char *username;
	pam_handle_t *pamh;
	int pam_status = PAM_SUCCESS;
	struct pam_conv pam_conv;

	if (argc < 3)
		return 1;

	username = argv[1];

	pam_conv.conv = conv;
	pam_conv.appdata_ptr = argv[2];

	pam_status = pam_start("xlock", username, &pam_conv, &pamh);
	if (pam_status != PAM_SUCCESS)
		return 2;

	pam_status = pam_authenticate(pamh, 0);

	printf("PAM said %s\n", pam_strerror(pamh, pam_status));

	pam_end(pamh, pam_status);

	return 0;
}

int conv(int num_msg, const struct pam_message **msg,
		struct pam_response **resp, void *appdata_ptr) {
	int i;
	char *usrresp;
	struct pam_response *struct_response;

	for (i = 0; i < num_msg; ++i) {
		printf("Message(%s): [%s]\n",
				msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ? "PAM_PROMPT_ECHO_OFF" :
				msg[i]->msg_style == PAM_PROMPT_ECHO_ON ? "PAM_PROMPT_ECHO_ON" :
				msg[i]->msg_style == PAM_ERROR_MSG ? "PAM_ERROR_MSG" :
				msg[i]->msg_style == PAM_TEXT_INFO ? "PAM_TEXT_INFO" :
				"unknown",
				msg[i]->msg);
	}
	printf("(end of messages)\n\n");

	usrresp = malloc(128);
	if (!usrresp)
		return PAM_BUF_ERR;

	struct_response = malloc(128);
	if (!struct_response)
		return PAM_BUF_ERR; /* leak */

	struct_response->resp_retcode = 0;
	struct_response->resp = strcpy(usrresp, appdata_ptr);

	*resp = struct_response;

	return PAM_SUCCESS;
}

/* vim:ts=4:sw=4:noet
 */
