#ifndef PAM_CLIENT_H
#define PAM_CLIENT_H

/* ******************************************************************* *
 * Copyright (c) 1998 Andrew G. Morgan <morgan@linux.kernel.org>
 * All rights reserved.
 *
 * The license for this source code should accompany this file.  Its
 * md5 checksum is: cac41ac118b52c96cf248baec7237381
 *
 * A client-side complement to PAM...  This library is not (yet) part of
 * The X/Open implementation of PAM.  Instead it is a Linux-PAM extension
 * that defines a "convention" for non-textual conversations.
 *
 * In the spirit of PAM, this code is defined to offer authenticating
 * clients pluggable authentication extensions.
 *
 * This code defines the extremely simple protocol tokens for
 * server <-> client and client <-> agent "binary" authentication exchange.
 *
 * The conventions demand that all 'data' transfer is represented in
 * maximally packed highest byte first order (8n-bit integers occupy n
 * bytes and the most significant byte is first in the data stream).
 * The mode of encapsulation between client and server is not defined
 * but is at the discretion of the application.
 * ******************************************************************* */

/*
 * Some conventions for conversation between client and authentication
 * agent.  Note, the action cycle of the agent is always:
 *
 *       1. wait for input from client.
 *       2. return acknowledgement to client, or exit.
 */

/* agent requests client sets an environment variable:
 * convention:
 *        "variable=value"    - set "variable" to "value"
 *        "variable="         - set "variable" to set-but-empty
 *        "variable"          - delete the "variable" from environment
 */

/*
 * This is an opaque data structure that keeps links to loaded
 * authentication agents.
 */

typedef struct pamc_handle_struct *pamc_handle_t;

/*
 * this type defines a _pointer_ to a data packet.  The data packet looks
 * like:
 *        { (__u32) 4+length, (__u32) control_type, (_u8) data[length] }.
 *
 *   length  - the length of the data[].
 *   control_type - one of four PAMC_CONTROL_{SELECT,EXCHANGE,DONE,EMPTY}
 *   data    - binary data payload (form is implied by current context).
 *
 * As a matter of policy all data packets should be scrubbed before
 * being liberated.  Note, no alignment can be assumed for the packet,
 * so all reading and writing of __u32 integers should be via __u8's
 * see macros.
 */

typedef unsigned char *pamc_packet_t;

/*
 * some macros for reading/writing numeric types.  'x' is (__u8 *)
 * 'y' is (__u32)
 */

#define pamc_read__u32(x) ((((x)[0])<<24)|(((x)[1])<<16)| \
			   (((x)[2])<<8)|(x)[3])

#define pamc_write__u32(x,y)                         \
     ((x)[0]=((y)>>24), (x)[1]=((y)>>16)&0xFF,       \
      (x)[2]=((y)>>8)&0xFF, (x)[3]=(y)&0xFF)

#define pamc_packet_length(packet)  pamc_read__u32(packet)
#define pamc_packet_data(packet)    ((packet)+4)

/*
 * client<->agent control codes
 */

/* These return codes indicate the auth agent -> client returns */
#define PAMC_CONTROL_OK              0      /* operation succeeded */
#define PAMC_CONTROL_FAIL            1      /* operation failed */
#define PAMC_CONTROL_BUSY            2      /* an agent was busy */

/* These are controls from the agent for execution by the client */

#define PAMC_CONTROL_ABORT        1000      /* agent terminated due to error */
#define PAMC_CONTROL_EXIT         1001      /* agent should exit (return code
					     * of zero means agent was happy
					     * to do that. */

#define PAMC_CONTROL_PUTENV       1100      /* agent gives client env-var */
#define PAMC_CONTROL_GETENV       1101      /* agent wants client env-var */
#define PAMC_CONTROL_GETECHO      1102      /* agent wants echoed input */
#define PAMC_CONTROL_GETNOECHO    1103      /* agent wants hidden input */
#define PAMC_CONTROL_PUTTEXT      1104      /* agent wants to echo text */

/* These are controls indicating agent <-> server message exchange
   (and reverse) */
#define PAMC_CONTROL_SELECT       2000      /* server's requests agent */
#define PAMC_CONTROL_EXCHANGE     2001      /* agent<->server exchanges info */
#define PAMC_CONTROL_DONE         2002      /* agent has completed */
#define PAMC_CONTROL_EMPTY        2003      /* agent has nothing to report */

/*
 * Library API functions:
 *
 * XXX - not sure we need to make pamc_set_agent visible.
 */

extern pamc_handle_t pamc_set_path(const char *path);
extern int pamc_end(pamc_handle_t *pch);
extern int pamc_set_agent(pamc_handle_t pch, const char *agent_id);
extern void pamc_delete_packet(pamc_packet_t *datum_pp);
extern void pamc_new_packet(pamc_packet_t *datum_pp, int length);
extern int pamc_exch_packet(pamc_handle_t pch, unsigned int control,
			    pamc_packet_t *datum_pp);

/*
 * some helper functions that are useful for both agent and client
 */

extern void pamc_scrub(void **data, int length);
extern int pamc_push_data(int fd, const void *data, int length);
extern int pamc_pull_data(int fd, void *data, int length);
extern int pamc_silent_fd(int fd);

#endif /* PAM_CLIENT_H */
