#include <stdio.h>
#include <stdlib.h>

#include <security/pam_modules.h>
#include <security/pam_client.h>

#undef DEBUG

#include <security/_pam_macros.h>


#define PLUGINNAME    "testing"
#define PLUGINNAMELEN (sizeof(PLUGINNAME)-1)

#define MSG1          "hello\nworld"
#define MSG1LEN       (sizeof(MSG1)-1)

int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,
			const char **argv)
{
    struct pam_message msg[2],*pmsg[2];
    struct pam_response *resp=NULL;
    pamc_packet_t packet1=NULL, packet2=NULL;
    struct pam_conv *conv;
    int retval;
    unsigned length, control;

    D(("called"));

    /* please load "testing" authentication agent */
    pamc_new_packet(&packet1, 4+PLUGINNAMELEN);     /* not <NUL> terminated! */
    pamc_write__u32(pamc_packet_data(packet1), PAMC_CONTROL_SELECT);
    memcpy(4+pamc_packet_data(packet1), PLUGINNAME, PLUGINNAMELEN);
    D(("%.8x %.8x", pamc_read__u32(packet1), pamc_read__u32(4+packet1)));
    msg[0].msg_style = PAM_BINARY_PROMPT;
    msg[0].msg = (const char *) packet1;
    pmsg[0] = &msg[0];
    D(("made select"));

    /* here is the data for that agent */
    pamc_new_packet(&packet2, 4+MSG1LEN);     /* not <NUL> terminated! */
    pamc_write__u32(pamc_packet_data(packet2), PAMC_CONTROL_EXCHANGE);
    memcpy(4+pamc_packet_data(packet2), MSG1, MSG1LEN);
    D(("%.8x %.8x", pamc_read__u32(packet1), pamc_read__u32(4+packet1)));
    msg[1].msg_style = PAM_BINARY_PROMPT;
    msg[1].msg = (const char *) packet2;
    pmsg[1] = &msg[1];

    D(("made message"));

    /* let's converse about it */
    retval = pam_get_item(pamh,PAM_CONV,(const void **)&conv);
    D(("getting conversation fn(): %s", pam_strerror(pamh, retval)));

    D(("message: %.4s", pmsg[0]->msg+8));
    retval = conv->conv(2, (const struct pam_message **) pmsg
			, &resp, conv->appdata_ptr);
    D(("conversation returned: %s", pam_strerror(pamh, retval)));

    /* clean up */
    pamc_delete_packet(&packet1);
    pamc_delete_packet(&packet2);

    if (retval != PAM_SUCCESS) {
	D(("error from conversation function: %s",
	   pam_strerror(pamh, retval)));
 	return retval;
    }

    packet1 = (pamc_packet_t) resp[0].resp;
    length = pamc_packet_length(packet1);
    D(("length returned for packet[0] is %u", length));
    control = pamc_read__u32(pamc_packet_data(packet1));
    D(("control returned for packet[0] is %u", control));
    pamc_delete_packet(&packet1);

    packet2 = (pamc_packet_t) resp[1].resp;
    length = pamc_packet_length(packet2);
    D(("length returned for packet[1] is %u", length));
    control = pamc_read__u32(pamc_packet_data(packet2));
    D(("control returned for packet[1] is %u", control));
    pamc_delete_packet(&packet2);

    D(("done"));
    return PAM_AUTH_ERR;
}

int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc,
			const char **argv)
{
    D(("called"));
    D(("done"));
    return PAM_AUTH_ERR;
}

