/*
Copyright (c) 2010, Dirk Krause
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 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/


/**	@file	useraud.h	Public definitions for the useraud daemon.
 */


#ifndef USERAUD_H_INCLUDED

/**	Avoid multiple includions.
 */
#define USERAUD_H_INCLUDED 1

/**	Maximum line size in useraud protocol.
 */
#define USERAUD_LINESIZE	1024


/**	One response line from useraud.
 */
typedef struct {
	unsigned long	lineno;	/**< Line number. */
	char		*text;	/**< Line contents. */
} USERAUD_RESPONSE_LINE;


/**	One connection to a useraud daemon.
 */
typedef struct {
	char		*sockname;	/**< File name of UNIX domain socket. */
	int		 ec;		/**< Error code of last error. */
} USERAUD_CONNECTION;


/**	One response to a useraud request.
 */
typedef struct {
  	dk_storage_t	*s_r;	/**< Collection of USERAUD_CONNECTION. */
	dk_storage_iterator_t	*i_r;	/**< Iterator through collection. */
} USERAUD_RESPONSE;


/**	@defgroup	errorcodes	Error codes. */
/*@{*/
/** No error occured. */
#define UA_ERROR_NONE			0

/** Not enough memory. */
#define UA_ERROR_MEMORY			1

/** Syntax error in configuration file. */
#define UA_ERROR_SYNTAX			2

/** Internal error (bug). */
#define UA_ERROR_INTERNAL		3

/** Illegal arguments. */
#define UA_ERROR_ILLEGAL_ARGUMENTS	4

/** No response received from backend. */
#define UA_ERROR_NO_RESPONSE		5

/** Socket name too long (must be less than 108). */
#define UA_ERROR_SOCKET_NAME_TOO_LONG	6

/** Failed to create a socket. */
#define UA_ERROR_SOCKET_FAILED		7

/** Failed to connect to the useraud daemon. */
#define UA_ERROR_CONNECT_FAILED		8
/*@}*/


/**	@defgroup	apicommands	API commands. */
/*@{*/
/** Check whether backend is available. */
#define UA_API_AVAILABLE	0

/** Create backend-specific struct. */
#define UA_API_CREATE_DATA	1

/** Destroy backend-specific struct, */
#define UA_API_DESTROY_DATA	2

/** Process a configuration line. */
#define UA_API_CONFLINE		3

/** Check configuration. */
#define UA_API_CHECK_CONFIG	4

/** Find named user. */
#define UA_API_GET_USER		5
/*@}*/

/** @defgroup	requests	Request and response types. */
/*@{*/
/** Request: Logname and password (short response).
Check whetheror not the password is correct for the user name.
On success return a status code only.
Normal responses: 200 (success), 400 (wrong logname) or
401 (wrong password).
*/
#define UA_RQ_LOGNAME_PASSWORD		100

/** Request: Logname and password (long response).
Check whether or not the password is correct for the user name.
On success return detailed information about the user.
Normal responses: 300 (success), 400 (wrong logname) or
401 (wrong password).
*/
#define UA_RQ_LOGNAME_PASSWORD_LONG	101

/** Request: Logname, password and IP address (short response).
Check whether or not the password is correct for the user name.
On success return a status code and a cookie which can be used in
combination with the IP address to identify the user later.
Normal responses: 201 (success), 400 (wrong logname) or
401 (wrong password).
*/
#define UA_RQ_LOGNAME_PASSWORD_IP	102

/** Request: Logname, password and IP address (long response).
Check whether or not the password is correct for the user name.
On success return detailed information about the user and a cookie.
Normal responses: 301 (success), 400 (wrong logname) or 
401 (wrong password).
*/
#define UA_RQ_LOGNAME_PASSWORD_IP_LONG	103

/** Request: IP address and cookie (short response).
Authenticate a user by cookie and IP address. On success return
a status code.
Normal responses: 202 (success), 403 (no such cookie) or
404 (user inactive for too long).
*/
#define UA_RQ_IP_COOKIE			104

/** Request: IP address and cookie (long response). */
#define UA_RQ_IP_COOKIE_LONG		105

/** Request: Logname and algorithms. */
#define UA_RQ_GET_CHALLENGE		106

/** Request: Logname, challengetype, challenge and response. */
#define UA_RQ_RESPONSE			107

/** Request: Logname, challengetype, challenge and response (long response). */
#define UA_RQ_RESPONSE_LONG		108

/** Request: Logout for IP address and cookie. */
#define UA_RQ_LOGOUT			109

/** Request: Verify a user name. */
#define UA_RQ_VERIFY_LOGNAME		110

/** Request: Verify a user name and return details about the user. */
#define UA_RQ_VERIFY_DETAILED		111

/** Return code: Success. */
#define UA_RC_SUCCESS			200

/** Return code: Success for cookie. */
#define UA_RC_SUCCESS_COOKIE		201

/** Return code: Success: Logname verified. */
#define UA_RC_SUCCESS_LOGNAME		202

/** Return code: Success: Challenge. */
#define UA_RC_SUCCESS_CHALLENGE		203

/** Return code: Success: Full information. */
#define UA_RC_SUCCESS_FULL		300

/** Return code: Success: Full information and cookie. */
#define UA_RC_SUCCESS_FULL_WITH_COOKIE	301

/** Return code: Success: Full information for cookie. */
#define UA_RC_SUCCESS_COOKIE_FULL	302

/** Return code: Line contains additional data. */
#define UA_RC_ADDITIONAL_DATA		500

/** Return code: Final line. */
#define UA_RC_FINAL_LINE		600

/** Return code: ERROR: Error while operating on socket. */
#define UA_RC_ERR_SOCKET		400

/** Return code: ERROR: No such user. */
#define UA_RC_ERR_NO_SUCH_USER		401

/** Return code: ERROR: Wrong credentials. */
#define UA_RC_ERR_WRONG_CREDENTIALS	402

/** Return code: ERROR: No such cookie. */
#define UA_RC_ERR_NO_SUCH_COOKIE	403

/** Return code: ERROR: User inactive for too long. */
#define UA_RC_ERR_INACTIVE_TOO_LONG	404

/** Return code: ERROR: Algorithm unacceptable for backends. */
#define UA_RC_ERR_ALGORITHM_BE		405

/** Return code: ERROR: Algorithm mismatch. */
#define UA_RC_ERR_ALGORITHM_OTHERS	406

/** Return code: ERROR: No such challenge. */
#define UA_RC_ERR_NO_SUCH_CHALLENGE	407

/** Return code: ERROR: Challenge timed out (response too late). */
#define UA_RC_ERR_CHALLENGE_TIMEOUT	408

/** Return code: ERROR: Insufficient resources. */
#define UA_RC_ERR_RESOURCES		409

/** Return code: ERROR: Internal error. */
#define UA_RC_ERR_INTERNAL		410

/** Return code: ERROR: Protocol error. */
#define UA_RC_ERR_PROTOCOL		411
/*@}*/


#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UACL_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif

#ifdef __cplusplus
extern "C" {
#endif

/**	Create a connection data structure, save the socket name for later use.
 * 	@param	sockname	Socket name for connection to useraud.
 * 	@return	Pointer to new data structure on success, NULL on error.
 */
EXTERN
USERAUD_CONNECTION *
uacl_open DK_PR((char *sockname));

/**	Destroy a connection data structure.
 * 	@param	uc	Useraud connection data structure to destroy.
 */
EXTERN
void
uacl_close DK_PR((USERAUD_CONNECTION *uc));

/**	Process one request.
 * 	The data structure returned on success is created in dynamically
 * 	allocated memory.
 * 	To process the response lines use uacl_response_reset() first,
 * 	multiple calls to uacl_response_line() will return the reponse
 * 	text lines one by one.
 * 	Finally use uacl_response_close() to release the memory used
 * 	by the data structure.
 * 	@param	uc	Connection data structure.
 * 	@param	request	The request line to send to useraud.
 * 	@return	Pointer to a response structure on success, NULL on error.
 */
EXTERN
USERAUD_RESPONSE *
uacl_process DK_PR((USERAUD_CONNECTION *uc, char *request));

/**	Reset response structure before beginning to retrieve all lines.
 * 	@param	u	Response data structure.
 */
EXTERN
void
uacl_response_reset DK_PR((USERAUD_RESPONSE *u));

/**	Retrieve one response line from the response data structure.
 * 	@param	u	Response data structure.
 * 	@return	Pointer to the text on success, NULL on error or end.
 */
EXTERN
char *
uacl_response_line DK_PR((USERAUD_RESPONSE *u));

/**	Close response data structure, release memory.
 * 	@param	u	Response data structure to destroy.
 */
EXTERN
void
uacl_response_close DK_PR((USERAUD_RESPONSE *u));

#ifdef __cplusplus
};
#endif


#endif

