/*
 * Copyright (c) 2003-2016
 * Distributed Systems Software.  All rights reserved.
 * See the file LICENSE for redistribution information.
 *
 * $Id: auth.h 2925 2016-11-09 17:01:21Z brachman $
 */

/*****************************************************************************
 * COPYRIGHT AND PERMISSION NOTICE
 * 
 * Copyright (c) 2001-2003 The Queen in Right of Canada
 * 
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, and/or sell
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, provided that the above copyright notice(s) and this
 * permission notice appear in all copies of the Software and that both the
 * above copyright notice(s) and this permission notice appear in supporting
 * documentation.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE 
 * BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
 * SOFTWARE.
 * 
 * Except as contained in this notice, the name of a copyright holder shall not
 * be used in advertising or otherwise to promote the sale, use or other
 * dealings in this Software without prior written authorization of the
 * copyright holder.
 ***************************************************************************/

#ifndef _AUTH_H_
#define _AUTH_H_

#include "local.h"

/* For byteorder stuff */
#include <netinet/in.h>
#include <sys/param.h>

#include "dacs_crypto.h"

/*
 * For Rijndael (AES), these three key sizes are valid:
 * 128 bits (16 bytes), 192 bits (24 bytes), and 256 bits (32 bytes)
 */
enum {
  AUTH_CRYPT_KEY_LENGTH = 16		/* in bytes */
};

/* Do not change these unless you understand exactly how they are used. */
enum {
  /*
   * A minimum random padding length of zero is allowed but is unwise and
   * may compromise security.  Use at least 8.
   * The maximum length should be "significant" but not so much as to
   * make cookies very large.
   */
  AUTH_MIN_RANDOM_PADDING_LENGTH	= 8,
  AUTH_MAX_RANDOM_PADDING_LENGTH    = 37,
  AUTH_MAX_CREDENTIALS				= 10,
  AUTH_MAX_ROLE_STR_LENGTH			= 200,
  AUTH_CREDENTIALS_UNIQUE_BYTES     = 8,

  /*
   * This selects the method to use for generating IVs for encryption.
   * See crypt.c:make_iv()
   */
  AUTH_USE_RANDOMIZED_IV		    = 0,

  /* Number of seconds to delay if authentication fails.  May be zero. */
  AUTH_DEFAULT_FAIL_DELAY_SECS      = 8
};

/*
 * Raw USERNAME/PASSWORD/AUXILIARY limits - see auth.c
 * These are intended to be reasonable upper limits, but they may be
 * adjusted if necessary.
 */
enum {
  AUTH_MAX_INPUT_USERNAME_LENGTH    = 64,
  AUTH_MAX_INPUT_PASSWORD_LENGTH    = 128,
  AUTH_MAX_INPUT_AUX_LENGTH         = 128
};

/*
 * Bit flags
 * See authlib.c:auth_style_from_string()
 */
#define AUTH_STYLE_PASSWORD   (1 <<  0)
#define AUTH_STYLE_CERT       (1 <<  1)
#define AUTH_STYLE_PROMPTED   (1 <<  2)
#define AUTH_STYLE_NATIVE     (1 <<  3)
#define AUTH_STYLE_EXPR       (1 <<  4)
#define AUTH_STYLE_ADMIN      (1 <<  5)
#define AUTH_STYLE_IMPORTED   (1 <<  6)
#define AUTH_STYLE_ALIEN      (1 <<  7)
#define AUTH_STYLE_GENERATED  (1 <<  8)
#define AUTH_STYLE_DIGEST     (1 <<  9)
#define AUTH_STYLE_CAS        (1 << 10)
#define AUTH_STYLE_SIMPLE     (1 << 11)
#define AUTH_STYLE_ACS        (1 << 12)
#define AUTH_STYLE_MINFOCARD  (1 << 13)
#define AUTH_STYLE_SINFOCARD  (1 << 14)
#define AUTH_STYLE_INFOCARD   (1 << 15)
#define AUTH_STYLE_RLINK      (1 << 16)
#define AUTH_STYLE_SET_ROLES  (1 << 17)
#define AUTH_STYLE_ADD_ROLES  (1 << 18)
#define AUTH_STYLE_TGMA		  (1 << 19)
#define AUTH_STYLE_UNKNOWN    (1 << 20)

typedef int Auth_style;

/* Prefix of variable names used for prompting. */
#define AUTH_PROMPT_VAR_PREFIX      "AUTH_PROMPT_VAR"

#define AUTH_VALID_FOR_ACS			"acs"
#define AUTH_VALID_FOR_CHAINING		"chaining"
#define AUTH_VALID_FOR_IDENT		"ident"
#define AUTH_VALID_FOR_TRANSFER		"transfer"
#define AUTH_VALID_FOR_NOTHING		"nothing"

/*
 * This is the default lifetime, in seconds, of DACS admin credentials.
 * They are used in certain internal (DACS-to-DACS) transactions.
 * Although they are only supposed to be held by trusted components, because
 * they can convey special privileges their lifetime should not be any
 * longer than necessary.  It is sometimes necessary to increase this lifetime
 * when debugging or if a recipient server is slow.
 */
#define AUTH_CREDENTIALS_ADMIN_DEFAULT_LIFETIME_SECS	"20"

/*
 * At least one of these two strings must contain one or more characters
 * that are rejected by is_valid_auth_username().
 * Do not change these unless you fully understand how they are used.
 */
#define AUTH_ADMIN_USERNAME_PREFIX_STR	"*"
#define AUTH_ADMIN_USERNAME_SUFFIX_STR	"*"

#define AUTH_UA_HASH_DIGEST_NAME		"SHA1"

/*
 * Credentials describe an authenticated user (i.e., a DACS identity).
 * Externally, an XML representation is encrypted and then encoded as text
 * for transmission as the value part of a cookie, an HTTP extension header,
 * and so on.
 *
 * A (presumably) unique string identifies these credentials (and is used
 * to establish an audit trail and to associate proxy authorization with
 * particular credentials).
 *
 * XXX We assume that a time_t is an unsigned long.
 */
typedef struct Credentials {
  char *federation;
  char *username;			/* User's name within the home_jurisdiction */
  char *home_jurisdiction;	/* Jurisdiction that authenticated */
  char *ip_address;			/* User's IP address, maybe */
  char *role_str;
  time_t auth_time;			/* Absolute date/time of creation */
  time_t expires_secs;		/* Absolute date/time of expiry, relative to */
                            /* the clock at home_jurisdiction */
  Auth_style auth_style;
  char *version;
  char *valid_for;			/* Values: "acs", "chaining", or "ident" */
  char *imported_by;		/* Importing jurisdiction, if non-NULL */
  char *ua_hash;
  char *unique;				/* Unique identifier for these credentials */

  /* The following fields are not used externally */
  Group_name **roles;
  char *cookie_name;		/* Corresponding cookie name */
  int selected;
  struct Credentials *next;
} Credentials;

typedef struct Scredentials_selected {
  char *federation;
  char *jurisdiction;
  char *username;
  char *unique;
  char *version;
  struct Scredentials_selected *next;
} Scredentials_selected;

typedef struct Scredentials_unauth {
  char *federation;
} Scredentials_unauth;

typedef struct Scredentials {
  Scredentials_selected *selected;
  Scredentials_unauth *unauth;
} Scredentials;

typedef struct Cookie_name {
  char *app_name;		/* Always "DACS" */
  char *federation;
  char *jurisdiction;
  char *username;
  char *special;		/* e.g., "SELECTED" */
} Cookie_name;

typedef enum {
  COOKIE_NETSCAPE      = 0,
  COOKIE_EXT_NETSCAPE  = 1,
  COOKIE_RFC2109       = 2,
  COOKIE_RFC2965       = 3,
  COOKIE_RFC6265       = 4
} Cookie_syntax;

#define DACS_COOKIE_APP_NAME		"DACS"

typedef struct Cookie_name_terminators {
  char *app_end;				/* Terminates the application name. */
  char *federation_end;			/* Terminates the federation name. */
  char *jurisdiction_end;		/* Terminates the jurisdiction name. */
  char *username_end;			/* Terminates the username, if required. */
} Cookie_name_terminators;

/* Netscape format plus RFC extensions */
typedef struct Cookie {
  Cookie_syntax syntax;
  char *str;			/* The unparsed string for this cookie */
  char *name;			/* The unparsed name of this cookie */
  Cookie_name *parsed_name;
  char *value;
  char *domain;
  char *path;
  char *expires;
  char *max_age;		/* RFC 2109/2965 */
  char *comment;		/* RFC 2109/2965 */
  char *version;		/* RFC 2109/2965 */
  char *comment_url;	/* RFC 2965 */
  char *discard;		/* RFC 2965 */
  char *port;			/* RFC 2965 */
  int secure;
  int httponly;			/* Microsoft extension */
  int set_void;			/* If non-zero, ask client to delete it */
  struct Cookie *next;
} Cookie;

#ifdef CURRENT_CREDENTIALS
typedef struct Current_credentials {
  char *federation;
  char *username;
  char *home_jurisdiction;
  char *unique;
  struct Current_credentials *next;
} Current_credentials;
#endif

/* Reasons why authentication can fail. */
typedef enum {
  AUTH_FAILURE_REASON_INVALID_INFO   = 800,
  AUTH_FAILURE_REASON_INTERNAL_ERROR = 801,
  AUTH_FAILURE_REASON_USER_ERROR     = 802,
  AUTH_FAILURE_REASON_ABORT          = 803,
  AUTH_FAILURE_REASON_UNKNOWN        = 899
} Auth_failure_reason;

typedef enum {
  AUTH_REVOKE_DENY         = 1,
  AUTH_REVOKE_REVOKE       = 2,
  AUTH_REVOKE_COMMENT      = 3,
  AUTH_REVOKE_DISABLE      = 4,
  AUTH_REVOKE_BLOCK        = 5
} Revocation_type;

typedef struct Revocation {
  Revocation_type type;
  char *item;
} Revocation;

typedef struct Cred_cache {
  Cookie *cookies;
  Dsvec *auth;
} Cred_cache;

typedef struct Cred_auth_url {
  char *name;
  char *url;
} Cred_auth_url;

/*****************************************************/

typedef struct Roles_reply_ok {
  char *roles;
} Roles_reply_ok;

typedef struct Roles_reply_failed {
  char *reason;
} Roles_reply_failed;

typedef struct Roles_reply {
  Roles_reply_ok *ok;
  Roles_reply_failed *failed;
  Common_status *status;
} Roles_reply;

/*****************************************************/

typedef struct Auth_reply_ok {
  char *username;
  char *lifetime;
  Roles_reply *roles_reply;
} Auth_reply_ok;

typedef struct Auth_reply_failed {
  char *username;
  char *redirect_url;
} Auth_reply_failed;

#ifdef NOTDEF
typedef struct Auth_reply_error {
  char *reason;
} Auth_reply_error;
#endif

typedef struct Auth_prompt {
  char *type;
  char *label;
  char *varname;
  struct Auth_prompt *next;
} Auth_prompt;

typedef struct Auth_prompts {
  char *transid;
  Auth_prompt *head;
} Auth_prompts;

typedef struct Auth_reply {
  Auth_reply_ok *ok;
  Auth_reply_failed *failed;
  Common_status *status;
  Auth_prompts *prompts;
} Auth_reply;

/*****************************************************/

/* Used by local_cas_authenticate. */

typedef struct Cas_auth {
  char *server_uri;
  char *redirect_args;
  char *session_ticket;
  char *redirect_url;
  char *username;		/* The username, if determined by CAS */
  char *roles;			/* For DACS, non-standard */
} Cas_auth;

/*****************************************************/

/* Used by dacs_auth_tgma and local_tgma_authenticate. */

/* Used to sign the hidden CGI variables on the login page. */
#define TGMA_HMAC_DIGEST_NAME		"SHA3-256"

/* Used to hash the Instance ID. */
#define TGMA_IID_DIGEST_NAME		"SHA3-256"

#define TGMA_SRP_DIGEST_NAME		"SHA3-256"

enum {
  TGMA_DEFAULT_WINDOW_SECS = 100,
  TGMA_MIN_IID_LENGTH      = 4,
  /* Number of random characters comprising an instance id. */
  TGMA_INSTANCE_ID_NBYTES  = 4
};

typedef struct Tgma_auth {
  char *iid;
  char *clock_str;
  char *nonce;
  char *sig_str;
  char *window_str;
  char *addr_str;
  int use_tcp;
} Tgma_auth;

/*****************************************************/

/* Used by local_http_authenticate. */
typedef struct Url_auth {
  Http_method method;
  char *url;
  char *username_parameter;
  char *password_parameter;
  Dsvec *options;
} Url_auth;

/*****************************************************/

/* Used by local_pam_authenticate. */

enum {
  /* Maximum time for pamd to wait for a reply from the client. */
  PAMD_USER_TIMEOUT_SECS = 60,
  /* Maximum time for local_pam_authenticate to wait for a reply from pamd. */
  PAMD_PAMD_TIMEOUT_SECS = 20
};

/*
 * This will typically be the name of a file in /etc/pam.d containing
 * the PAM policy to be used by local_unix_pam_auth().
 * It can be overridden by an OPTION.
 * The module requires the policy to prompt for exactly one thing: a password.
 */
#ifndef DEFAULT_PAM_SERVICE
#define DEFAULT_PAM_SERVICE		"dacs-unix-auth"
#endif

/*
 * This is the prompt we expect PAM to ask to be emitted, case-insensitively,
 * for Unix password validation. Trailing spaces are always ignored; do not
 * add them here.  You might need to change this if the prompt is in some
 * other language, for instance.
 *
 * We do this check only to detect potential PAM or DACS misconfiguration.
 * If this is set to the empty string, no check will be performed and the
 * module will assume that everything is ok.
 */
#ifndef PAM_PASSWD_CONV_MSG
#define PAM_PASSWD_CONV_MSG		"Password:"
#endif

/*
 * For control of the Unix password type authentication via the
 * local_unix_auth() and local_unix_pam_auth() methods.
 */
typedef enum {
  AUTH_UNIX_WITHOUT_PAM = 0,	/* Do not use local_unix_pam_auth(). */
  AUTH_UNIX_USE_PAM     = 1,	/* Only use local_unix_pam_auth(). */
  AUTH_UNIX_TRY_PAM     = 2,	/* Try local_unix_pam_auth() if necessary. */
  AUTH_UNIX_DEFAULT_PAM = AUTH_UNIX_TRY_PAM
} Auth_unix_pam;

/* Older versions of pam_strerror() didn't take the pam_handle_t argument. */
#ifdef PAM_STRERROR_USES_PAMH
#define PAM_STRERROR(HANDLE, ERR)		pam_strerror(HANDLE, ERR)
#else
#define PAM_STRERROR(HANDLE, ERR)		pam_strerror(ERR)
#endif

/*
 * This is (optionally) used to find the port used for pamd in /etc/services
 * and /etc/inetd.conf.
 */
#define PAMD_SERVICE_NAME	"dacs-pamd"

/*
 * The name of the default PAM policy.
 */
#define PAMD_DEFAULT_POLICY	"dacs"

/* Transaction/session identification (transid or tid) information. */
typedef struct Pam_auth_tid {
  char *str;
  char *host;
  in_port_t port;
  pid_t pid;
  char *unique;
} Pam_auth_tid;

/*****************************************************/

/* Used by local_grid_authenticate. */

enum {
  AUTH_GRID_NCOLS            = 10,
  AUTH_GRID_NROWS            = 10,
  AUTH_GRID_MIN_COLS         = 3,
  AUTH_GRID_MIN_ROWS         = 3,
  AUTH_GRID_MAX_COLS         = 26,
  AUTH_GRID_MAX_ROWS         = 99,
  AUTH_GRID_SERIAL_LENGTH    = 8,
  AUTH_GRID_CHALLENGE_LENGTH = 4,
  AUTH_GRID_CHALLENGE_SECS   = 60,
  AUTH_GRID_MIN_CHALLENGE    = 3,
  AUTH_GRID_PIN_LENGTH       = 2,
  AUTH_GRID_LIFETIME_SECS    = (60 * 60 * 24 * 7)	/* One week */
};

typedef struct Auth_grid {
  char *username;
  int enabled;
  int nrows;
  int ncols;
  char *serial;
  Dsvec *grid;
  char *pin;
  time_t date_created;
} Auth_grid;

/*****************************************************/

/* Used by dacstoken and local_token_authenticate. */

enum {
  TOKEN_HOTP_DEFAULT_ACCEPT_WINDOW  = 3,
  TOKEN_HOTP_SYNC_OTPS              = 3,
  TOKEN_HOTP_COUNTER_LENGTH         = 8,		/* in bytes (RFC 4226) */
  TOKEN_HOTP_NDIGITS                = 6,		/* the minimum (RFC 4226) */
  TOKEN_HOTP_BASE                   = 10,		/* recommended (RFC 4226) */
  TOKEN_HOTP_MAX_SYNC               = 10000,
  TOKEN_TOTP_NDIGITS                = 8,
  TOKEN_TOTP_BASE                   = 10,
  TOKEN_TOTP_DEFAULT_TIME_STEP_SECS = 30,
  TOKEN_TOTP_DEFAULT_DRIFT_WINDOW   = 2,
  TOKEN_TOTP_MAX_SYNC               = 20,
  TOKEN_MIN_NDIGITS                 = 6,
  TOKEN_MAX_NDIGITS                 = 9,
  TOKEN_MIN_KEY_LENGTH_BYTES        = 16		/* in bytes (RFC 4226) */
};

/* These are bit flags. */
enum {
  TOKEN_MODE_UNKNOWN  = 0x00,		/* Must be zero */
  TOKEN_MODE_COUNTER  = 0x01,		/* HOTP authentication */
  TOKEN_MODE_TIME     = 0x02,		/* TOTP authentication */
  TOKEN_MODE_MASK     = 0x0f,		/* 4 bits for the operation mode */
  TOKEN_MODE_DISABLED = 0x10,
  TOKEN_MODE_DEFAULT  = TOKEN_MODE_COUNTER
};

typedef enum {
  TOKEN_IGNORABLE_PIN = 0,
  TOKEN_REQUIRE_PIN   = 1
} Token_pin_mode;

/*
 * We would rather not assume that the HOTP counter length (currently defined
 * to be eight bytes long) corresponds to a native data type.
 * But it simplifies the code if we required it, so we'll worry about this
 * if and when the counter length is extended.
 */
typedef unsigned int Auth_token_mode;
#define AUTH_TOKEN_COUNTER_T unsigned long long
typedef AUTH_TOKEN_COUNTER_T Auth_token_counter;

#define TOKEN_HOTP_DEFAULT_HASH		"SHA1"
#define TOKEN_TOTP_DEFAULT_HASH		"SHA1"

/* Representation of a hardware token device, in memory. */
typedef struct Auth_token {
  char *username;				/* For internal use only */
  Auth_token_mode mode;			/* TOKEN_MODE_COUNTER or TOKEN_MODE_TIME */
  char *item_type;				/* For internal use only */
  char *digest_name;
  char *serial;					/* Device's serial number */
  unsigned char *counter;		/* Current counter value (HOTP only) */
  unsigned char *key;			/* Device's secret key/seed, in binary */
  unsigned int keylen;			/* For internal use only */
  unsigned int time_step;		/* In seconds (TOTP only) */
  int drift;					/* In seconds (TOTP only) */
  unsigned int ndigits;
  unsigned int base;
  char *pin_hash;				/* Digest of user's PIN (optional) */
  time_t last_update;			/* Date of last modification of this info */
} Auth_token;

/*****************************************************/

/* Used by local_apache_authenticate. */

/*
 * This indicates which module's authentication method needs to be reproduced.
 */
typedef enum {
  MOD_AUTH        = 0,
  MOD_AUTH_DBM    = 1,
  MOD_AUTH_DIGEST = 2,
  MOD_AUTH_NONE   = 3
} Apache_module;

/*
 * For MOD_AUTH_DBM, the database types that are supported by htdbm
 */
typedef enum {
  DBM_SDBM = 0,
  DBM_GDBM = 1,
  DBM_NDBM = 2,
  DBM_DB   = 3,
  DBM_NONE = 4
} Apache_dbm;

/*
 * The various hashes used by MOD_AUTH and MOD_AUTH_DBM
 */
typedef enum {
  HASH_MD5, HASH_CRYPT, HASH_SHA1, HASH_PLAIN
} Apache_hash;

typedef enum {
  AUTH_REQUIRED        = 1,
  AUTH_REQUISITE       = 2,
  AUTH_OPTIONAL        = 3,
  AUTH_SUFFICIENT      = 4,
  AUTH_USER_SUFFICIENT = 5
} Auth_control_flag;

typedef struct Auth_password_audit {
  char *varname;
  char *constraints;
} Auth_password_audit;

typedef struct Auth_module {
  char *id;
  Kwv_vartab *auth_vartab;
  char *url;
  char *url_eval;
  char *expr;
  char *init_eval;
  char *exit_eval;
  Auth_style style;
  Auth_control_flag control_flag;
  char *predicate;
  char **flags;
  Dsvec *options;
  Dsvec *options_eval;
  Dsvec *dsv_audits;
  Kwv *kwv_options;
  Kwv *kwv_conf;
  int have_req_auth;
  int result;
  Dsvec *argv_spec;
  struct Auth_module *next;
} Auth_module;

typedef struct Auth_module_info {
  Auth_module *modules;
  int mcount;
  int have_req_auth;
  int saw_expr;
  int saw_native;
  int saw_prompted;
  int saw_set_roles;
  int saw_add_roles;
} Auth_module_info;

/*
 * Each builtin authentication module is assigned an internal identifier
 * to avoid some string comparisons and to ensure consistent recognition of
 * abbreviated module names.
 */
typedef enum {
  AUTH_MODULE_EXPR     = 1,
  AUTH_MODULE_PASSWD   = 2,
  AUTH_MODULE_SIMPLE   = 3,
  AUTH_MODULE_INFOCARD = 4,
  AUTH_MODULE_UNIX     = 5,
  AUTH_MODULE_NTLM     = 6,
  AUTH_MODULE_APACHE   = 7,
  AUTH_MODULE_CAS      = 8,
  AUTH_MODULE_GRID     = 9,
  AUTH_MODULE_HTTP     = 10,
  AUTH_MODULE_TOKEN    = 11,
  AUTH_MODULE_PAM      = 12,
  AUTH_MODULE_TGMA     = 13,
  AUTH_MODULE_UNKNOWN  = -1
} Auth_module_id;

#define AUTH_MODULE_MAX_ALIASES		5

typedef struct Auth_module_desc {
  Auth_module_id id;
  int is_builtin;			/* Currently, only builtins. */
  Auth_style style;
  char *canonical_name;
  char *aliases[AUTH_MODULE_MAX_ALIASES];
} Auth_module_desc;

#include "acs.h"

typedef struct Roles_module {
  char *id;
  Kwv_vartab *roles_vartab;
  char *predicate;
  char *url;
  char *url_eval;
  char *expr;
  char *init_eval;
  char *exit_eval;
  Dsvec *options;
  Dsvec *options_eval;
  char *username;
  Kwv *kwv_options;
  Kwv *kwv_conf;
  Dsvec *argv_spec;
  struct Roles_module *next;
} Roles_module;

typedef struct Roles_module_info {
  Roles_module *modules;
  int mcount;
} Roles_module_info;

typedef enum {
  ROLES_MODULE         = 1,
  ROLES_MODULE_UNIX    = 2,
  ROLES_MODULE_EXPR    = 3,
  ROLES_MODULE_UNKNOWN = -1
} Roles_module_id;

#define ROLES_MODULE_MAX_ALIASES	5

typedef struct Roles_module_desc {
  Roles_module_id id;
  int is_builtin;
  char *canonical_name;
  char *aliases[ROLES_MODULE_MAX_ALIASES];
} Roles_module_desc;

/*****************************************************/

typedef enum {
  HTTP_AUTH_BASIC    = 0,
  HTTP_AUTH_DIGEST   = 1,
  HTTP_AUTH_EXCEPT   = 2,
  HTTP_AUTH_UNKNOWN  = 3
} Http_auth_scheme;

/* An HTTP_AUTH configuration directive */
typedef struct Http_auth {
  Http_auth_scheme scheme;
  char *scheme_name;
  char *realm;
  Dsvec *url_patterns;
  int pre_flag;
  char *param;
  Auth_module *auth_modules;
  Roles_module *roles_modules;
} Http_auth;

/* XXX may require code change where used. */
#define AUTH_DIGEST_NONCE_DIGEST_NAME	"SHA1"

/* A parsed WWW-Authentication response header */
typedef struct Http_auth_www_authenticate {
  char *www_authenticate;	/* The header value; its parsed fields follow */
  Http_auth_scheme scheme;
  char *scheme_name;
  char *realm;
  char *domain;
  char *nonce;
  char *opaque;
  char *stale;
  char *algorithm;
  char *qop_options;
  char *auth_param;
} Http_auth_www_authenticate;

/* A parsed Authorization request header */
typedef struct Http_auth_authorization {
  char *authorization;		/* The header value; its parsed fields follow */
  Http_auth_scheme scheme;
  char *scheme_name;
  char *username;
  char *password;
  char *realm;
  char *nonce;
  char *digest_uri;
  char *response;
  char *algorithm;
  char *cnonce;
  char *opaque;
  char *message_qop;
  char *nonce_count;
  char *auth_param;
  /*
   * The following are not part of the header but are put here for
   * convenience.
   */
  char *http_method;			/* In the canonical syntax (upper case) */
  Http_auth_www_authenticate *www_auth;
} Http_auth_authorization;

static inline MAYBE_UNUSED Apache_module
lookup_module(char *module_name)
{

  if (strcaseeq(module_name, "mod_auth")
	  || strcaseeq(module_name, "htpasswd"))
	return(MOD_AUTH);
  else if (strcaseeq(module_name, "mod_auth_digest")
		   || strcaseeq(module_name, "htdigest"))
	return(MOD_AUTH_DIGEST);
  else if (strcaseeq(module_name, "mod_auth_dbm")
		   || strcaseeq(module_name, "htdbm"))
	return(MOD_AUTH_DBM);

  return(MOD_AUTH_NONE);
}

static inline MAYBE_UNUSED Apache_dbm
lookup_dbm_type(char *dbm_type)
{

  if (strcaseeq(dbm_type, "sdbm"))
	return(DBM_SDBM);
  else if (strcaseeq(dbm_type, "gdbm"))
	return(DBM_GDBM);
  else if (strcaseeq(dbm_type, "ndbm"))
	return(DBM_NDBM);
  else if (strcaseeq(dbm_type, "db"))
	return(DBM_DB);

  return(DBM_NONE);
}

/*****************************************************/

/*
 * If PASSWORD_DIGEST not configured, this is the default password hashing
 * algorithm to use.
 */
#ifndef PASSWD_ALG_DEFAULT_NAME
#define PASSWD_ALG_DEFAULT_NAME		"SHA512"
#endif

/*
 * Default parameters for password hashing functions.
 */
#define PASSWD_DEFAULT_PBKDF2_SHA1_COUNT	16384
#define PASSWD_DEFAULT_PBKDF2_SHA1_DKLEN	32
#define PASSWD_DEFAULT_PBKDF2_SHA256_COUNT	32768
#define PASSWD_DEFAULT_PBKDF2_SHA256_DKLEN	32
#define PASSWD_DEFAULT_PBKDF2_SHA512_COUNT	32768
#define PASSWD_DEFAULT_PBKDF2_SHA512_DKLEN	64
#define PASSWD_DEFAULT_SCRIPT_N				131072
#define PASSWD_DEFAULT_SCRIPT_R				8
#define PASSWD_DEFAULT_SCRIPT_P				1
#define PASSWD_DEFAULT_SCRIPT_DKLEN			32
#ifdef NOTDEF
/* Alternatively: */
#define PASSWD_DEFAULT_SCRIPT_N				32768
#define PASSWD_DEFAULT_SCRIPT_R				8
#define PASSWD_DEFAULT_SCRIPT_P				8
#define PASSWD_DEFAULT_SCRIPT_DKLEN			64
#endif

enum {
  CRYPT_KEYS_RSA_KEY_LENGTH_1024 = 1024,
  CRYPT_KEYS_RSA_KEY_LENGTH_2048 = 2048,
  CRYPT_KEYS_RSA_KEY_LENGTH_4096 = 4096,
  CRYPT_KEYS_RSA_KEY_LENGTH_8192 = 8192,
  CRYPT_KEYS_RSA_KEY_LENGTH_DEFAULT = CRYPT_KEYS_RSA_KEY_LENGTH_2048
};

/*
 * Configuration for local DACS acounts.
 * Some of this is run-time configurable; see PASSWORD_* directives.
 */
enum {
  PASSWD_SALT_BYTES        = 16,
  PASSWD_MINIMUM_LENGTH    = 6,
  PASSWD_NEEDS_MIXED_CASE  = 0,		/* Set to zero to disable. */
  PASSWD_NEEDS_PUNCTUATION = 0,		/* Set to zero to disable. */
  PASSWD_NEEDS_DIGITS      = 0		/* Set to zero to disable. */
};

typedef enum {
  GET_PASSWD_FILE   = 0,
  GET_PASSWD_STDIN  = 1,
  GET_PASSWD_STREAM = 2,
  GET_PASSWD_PROMPT = 3
} Get_passwd_type;

typedef struct Pw_constraints {
  int minlen;
  int mixed_case;
  int punct;
  int digits;
} Pw_constraints;

/*
 * This character separates fields in a password entry.
 * It must be a printable character not produced by strba64().
 * If you change this, you will need to edit your DACS password files.
 */
#define PASSWD_SEP_CHAR		'|'

#define PASSWD_ALG_SEP_STR	","
/*
 * If this character is the first one in the stored digest entry,
 * the entry is in the disabled state and cannot be authenticated against.
 * If you change this, you will need to edit your DACS password files.
 */
#define PASSWD_DISABLED_CHAR	'*'

typedef enum {
  PW_STATE_UNCHANGED = 0,
  PW_STATE_DISABLED  = 1,
  PW_STATE_ENABLED   = 2
} Pw_state;

/*
 * Although for the most part these operations on accounts are mutually
 * exclusive, bit flags are used because some of them can be combined.
 */
typedef enum {
  PW_OP_NONE           = 0,			/* This one must be zero. */
  PW_OP_ADD            = (1 <<  0),
  PW_OP_DELETE         = (1 <<  1),
  PW_OP_LIST           = (1 <<  2),
  PW_OP_RESET          = (1 <<  3),
  PW_OP_DISABLE        = (1 <<  4),
  PW_OP_ENABLE         = (1 <<  5),
  PW_OP_UPDATE         = (1 <<  6),
  PW_OP_MODIFY         = (1 <<  7),
  PW_OP_SET_DATA       = (1 <<  8),
  PW_OP_DELETE_DATA    = (1 <<  9),
  PW_OP_GET_DATA       = (1 << 10),
  PW_OP_TEST_EXISTS    = (1 << 11),
  PW_OP_TEST_DISABLED  = (1 << 12),
  PW_OP_TEST_ENABLED   = (1 << 13),
  PW_OP_TEST_PRIVATE   = (1 << 14),
  PW_OP_GET_DIGEST     = (1 << 15),
  PW_OP_REGENERATE     = (1 << 16),
  PW_OP_LONGLIST       = (1 << 17)
} Pw_op;

/*
 * A password file entry in memory, as maintained by dacspasswd(1) etc.
 *
 * For parameterized digest algorithms, parameters (and the algorithm identifier)
 * are stored with each password entry, and the stored parameters are
 * always used for validation, so changing the configuration will not invalidate
 * previously stored passwords, only new or updated entries.
 */
typedef struct Pw_entry {
  char *username;		/* In memory only */
  Pw_state state;
  Digest_desc *dd;		/* Secure hash algorithm used on the password. */
  char *salt;
  char *digest;			/* Hash of a password and salt using alg */
  char *stored_digest;	/* Formatted alg, salt, and digest */
  char *entry;			/* The stored_digest with encoded application data */
  Ds *private;			/* Arbitrary application data */
} Pw_entry;

/*****************************************************/

/*
 * Convention: names associated with self-issued InfoCards begin with
 * "sic_" ("Sic_" and "SIC_"), those associated with managed InfoCards begin
 * with "mic_" ("Mic_" and "MIC_"), and those that are generic (common to
 * both types) are prefixed by "ic_" ("Ic_" and "IC_").
 * When the distinction isn't important, "INFOCARD_" is often used.
 */

#define INFOCARD_DEFAULT_STS_TITLE		"DACS Managed InfoCard IP/STS"
#define INFOCARD_CARD_IMAGE_PASSWD		"dacs_username_password_credential.png"
#define INFOCARD_CARD_IMAGE_CERT		"dacs_x509certificate_credential.png"
#define INFOCARD_CARD_IMAGE_CARD		"dacs_selfissued_credential.png"
#define INFOCARD_DIGEST_DEFAULT_NAME	"SHA256"
#define INFOCARD_ASSERTION_ID_PREFIX	"uuid-"
#define INFOCARD_DEFAULT_CARDID_SUFFIX	"identity"
#define INFOCARD_DEFAULT_STS_USERNAME_PASSWD_PROMPT_FMT	\
  "Enter your %s username and password"

enum {
  INFOCARD_DEFAULT_CARD_LIFETIME_SECS   = (60 * 60 * 24 * 365),
  INFOCARD_DEFAULT_TOKEN_LIFETIME_SECS  = 10	/* As short as reasonable. */
};

#define SIC_USERNAME_PREFIX		"SU|"
#define SIC_HASHSTR_PREFIX		"SH|"
#define MIC_IDENTITY_PREFIX		"MI|"
#define MIC_CARD_ID_PREFIX		"MC|"

/*
 * Various maximum values - they're tunable here; some may be overridden by
 * configuration directives.
 */
enum {
  IC_MAX_TOKEN_SIZE     = 16384,
  IC_MAX_DRIFT_SECS     = (5 * 60)
};

/*
 * Various maximum values for the STATIC and ISTATIC types of managed InfoCard.
 * They're tunable here; in the future some might be overridden by
 * configuration directives.
 */
enum {
  MIC_MAX_STATIC_CLAIMS           = 10,
  MIC_MAX_STATIC_NAME_CLAIM_SIZE  = 32,
  MIC_MAX_STATIC_VALUE_CLAIM_SIZE = 64,
  MIC_MAX_STATIC_URI_CLAIM_SIZE   = 128,
  MIC_MAX_STATIC_LABEL_CLAIM_SIZE = 20,
  MIC_MAX_STATIC_DESC_CLAIM_SIZE  = 40
};

/*
 * Various maximum values for the DACS and DYNAMIC types of managed InfoCard,
 * where external web services provide claim definitions.
 * They're tunable here; in the future some might be overridden by
 * configuration directives.
 */
enum {
  MIC_MAX_DYNAMIC_CLAIMS           = 20,
  MIC_MAX_DYNAMIC_NAME_CLAIM_SIZE  = 32,
  MIC_MAX_DYNAMIC_VALUE_CLAIM_SIZE = 64,
  MIC_MAX_DYNAMIC_URI_CLAIM_SIZE   = 128,
  MIC_MAX_DYNAMIC_LABEL_CLAIM_SIZE = 20,
  MIC_MAX_DYNAMIC_DESC_CLAIM_SIZE  = 40
};

typedef enum {
  IC_UNKNOWN_TYPE     = 0,
  IC_SELF_ISSUED_TYPE = 1,
  IC_MANAGED_TYPE     = 2
} Ic_type;

typedef enum {
  IC_UNCHANGED = 0,
  IC_DISABLED  = 1,
  IC_ENABLED   = 2
} Ic_state;

/* Managed InfoCard claim definition/fill usage modes. */
typedef enum {
  IC_USE_MODE_DACS    = 0,
  IC_USE_MODE_STATIC  = 1,
  IC_USE_MODE_ISTATIC = 2,
  IC_USE_MODE_DYNAMIC = 3,
  IC_USE_MODE_UNKNOWN = -1
} Ic_use_mode;

/* Managed InfoCard IP/STS authentication credential types. */
typedef enum {
  INFOCARD_AUTHTYPE_NONE      = 0,
  INFOCARD_AUTHTYPE_PASSWD    = 1,
  INFOCARD_AUTHTYPE_CERT      = 2,
  INFOCARD_AUTHTYPE_CARD      = 3,
  INFOCARD_AUTHTYPE_KERBEROS  = 4		/* Not supported */
} Ic_sts_authtype;

/*
 * Although for the most part these operations on accounts are mutually
 * exclusive, bit flags are used because some of them can be combined.
 */
typedef enum {
  IC_OP_NONE           = 0,			/* This one must be zero. */
  IC_OP_MODIFY         = (1 << 0),
  IC_OP_REGISTER       = (1 << 1),
  IC_OP_DELETE         = (1 << 2),
  IC_OP_LIST           = (1 << 3),
  IC_OP_DISABLE        = (1 << 4),
  IC_OP_ENABLE         = (1 << 5),
  IC_OP_SET_DATA       = (1 << 6),
  IC_OP_DELETE_DATA    = (1 << 7),
  IC_OP_TEST_EXISTS    = (1 << 8),
  IC_OP_TEST_ENABLED   = (1 << 9),
  IC_OP_TEST_DISABLED  = (1 << 10),
  IC_OP_TEST_PRIVATE   = (1 << 11),
  IC_OP_GET_DIGEST     = (1 << 12),
  IC_OP_GET_DATA       = (1 << 13),
  IC_OP_UPDATE         = (1 << 14),
  IC_OP_LOOKUP         = (1 << 15),
  IC_OP_TOKEN_VALIDATE = (1 << 16),
  IC_OP_TOKEN_ATTRVALS = (1 << 17)
} Ic_op;

/*
 * Stuff extracted from either a self-issued or managed InfoCard account.
 */
typedef struct Ic_auth {
  Ic_type type;
  Ic_state state;
  Ic_use_mode use_mode;
  char *username;
  char *roles;
  Kwv *kwv_claims;
} Ic_auth;

/*
 * A self-issued InfoCard account entry, in memory.
 * Note that the PPID (private personal identifier) is not stored.
 * See dacsinfocard.c
 */
typedef struct Sic_entry {
  Ic_state state;
  Digest_desc *desc;
  char *username;
  Ds *friendly_id;
  char *pubkey_modulus;
  char *pubkey_exponent;
  char *digest;
  Ds *private;
} Sic_entry;

typedef struct Mic_sts_auth {
  Ic_sts_authtype authtype;
  Digest_desc *desc;			/* For "passwd" type */
  char *digest;					/* For "passwd" type, optional */
  char *self_issued_ppid;		/* For "card" type */
  Ds *thumbprint;				/* For "cert" type */
} Mic_sts_auth;

typedef struct Mic_entry {
  char *identity;				/* DACS identity associated with this card. */
  Ic_state state;				/* Usable for authentication? */
  Ic_use_mode use_mode;			/* Method to obtain claims */
  char *card_id;
  Mic_sts_auth *sts_auth;
  Dsvec *claims;				/* (Icx_claim *) */
} Mic_entry;

typedef struct Ic_entry {
  Mic_entry *mic;
  Sic_entry *sic;
} Ic_entry;

/*
 * Configuration parameters to override lower-level defaults.
 */
typedef struct Ic_config {
  char *certfile;
  char *keyfile;
  Dsvec *audience;
  char *issuer;
  int enable_replay_detection;
  int enable_signature_validation;
  size_t max_token_size;
  int max_drift_secs;
} Ic_config;

typedef enum {
  IC_CONFIRM_HOLDER = 0,
  IC_CONFIRM_BEARER = 1,
  IC_CONFIRM_ERROR  = -1
} Ic_subj_confirm_method;

/*
 * Fields extracted from a SAML token received by a Relying Party.
 */
typedef struct Ic_token {
  char *issuer;						/* NULL if self issued */
  Ic_subj_confirm_method confirm;
  Ds *ppid;
  Ds *exponent;
  Ds *modulus;
  Kwv *kwv_claims;			/* Claim type (full URI)/claim value pairs */
} Ic_token;

/*****************************************************/

#include "dacs_crypto.h"

typedef struct Crypt_keys {
  char *fed_id;					/* Presumably unique federation id string */
  unsigned char *auth_key;		/* Binary key for authentication - internal */
  unsigned int auth_key_len;	/* Length of binary key, in bytes */
  char *auth_key_str;			/* Base-64 textual representation */
  unsigned char *hmac_key;		/* Binary key for keyed-hashing - internal */
  unsigned int hmac_key_len;	/* Length of HMAC key, in bytes */
  char *hmac_key_str;			/* Base-64 textual representation */
  char *public_key_str;			/* Base-64 representation of RSA public key */
  EVP_PKEY *public_key;			/* RSA public key - internal only */
  char *public_key_pem;			/* PEM version of RSA public key - internal */
  char *private_key_str;		/* Base-64 textual representation */
  EVP_PKEY *private_key;		/* RSA private key - Internal only */
  char *private_key_pem;		/* PEM version of RSA private key - internal */
} Crypt_keys;

extern char *non_auth_cookie_header;
extern Cookie *non_auth_cookies;
extern int debug_crypt;

extern const Cookie_name_terminators default_cookie_name_terminators;
extern Cookie_name_terminators current_cookie_name_terminators;


/*****************************************************/

typedef enum {
  USERINFO_AUTH    = 0,
  USERINFO_SIGNOUT = 1,
  USERINFO_ACCESS  = 2,
  USERINFO_ERROR   = 3
} User_info_type;

typedef struct User_auth {
  char *ident;
  char *ip;
  char *auth_time;
  char *expires;
  char *jurisdiction;
  char *auth_style;
  char *valid_for;
  char *unique;
  char *imported_by;
} User_auth;

typedef struct User_signout {
  char *ident;
  char *ip;
  char *date;
  char *jurisdiction;
  char *unique;
} User_signout;

typedef struct User_access {
  char *ident;
  char *ip;
  char *date;
  char *jurisdiction;
  char *host;
  char *addr;
  char *unique;
  char *uri;
} User_access;

typedef struct User_info {
  User_info_type which;
  union {
	User_auth auth;
	User_signout signout;
	User_access acs;
  } info;
} User_info;

/*****************************************************/

typedef struct Auth_out {
  int result;			/* 0 = failed, 1 = succeeded, -1 = error */
  char *identity;		/* Authenticated identity, if result is 1. */
  char *username;		/* Username component of the authenticated identity. */
  char *role_string;	/* Role string, if result is 1 and roles obtained. */
} Auth_out;

#ifdef __cplusplus
extern "C" {
#endif

extern Auth_module *auth_module_config(char **argv, int *ind,
									   Auth_module_info *ami);
extern Roles_module *roles_module_config(char **argv, int *ind);

extern int is_valid_username(const char *username);
extern int is_valid_auth_username(const char *username);
extern char *make_dacs_admin_name(char *basename);
extern int is_dacs_admin_name(char *username);

extern char *is_valid_valid_for(const char *valid_for);
extern void set_valid_for(Credentials *credentials, char *valid_for);

/* Password-style Message Digests */
extern char *passwd_hash(Digest_desc *dd, char *passwd, char *salt);

/* mkkey.c */
extern Crypt_keys *crypt_keys_from_vfs(char *vfs_ref);
extern Crypt_keys *crypt_keys_from_buf(char *keystr);
extern void crypt_keys_free(Crypt_keys *ck);
extern int parse_xml_crypt_keys(char *keyfile, Crypt_keys **crypt_keys);

extern int validate_credentials_ip(Credentials *cr, char *actual_ip_address,
								   char **errmsg);
extern int validate_credentials(Credentials *c, char *actual_ip_address,
								char **msg);
extern int verify_expiration(time_t expires_date, int *remaining);

extern int parse_xml_credentials(char *cookie, Credentials **credentials);
extern int parse_xml_auth_reply(char *reply_string, Auth_reply **auth_reply);
extern int parse_xml_roles_reply(char *reply_string, Roles_reply **rr);
extern time_t make_auth_expiry_delta(time_t auth_time, char *delta);
extern time_t make_auth_expiry(time_t auth_time, time_t delta_secs);
extern int crypt_init(void);
extern int crypt_md(unsigned char *inp,
					unsigned int len, int alg, unsigned char **outp);
extern int is_valid_role_str(char *role_str);

extern Credentials *make_credentials(char *fname, char *jname, char *username,
									 char *ip, char *role_str,
									 char *expires, Auth_style style,
									 char *validity, char *imported_by,
									 char *ua_str);
extern Credentials *make_admin_credentials(void);
extern Credentials *init_credentials(void);
extern int get_valid_credentials(Cookie *cookies, char *remote_addr,
								 int valid_for_acs, Credentials **credentials);
extern int credentials_to_auth_cookies(Credentials *credentials,
									   char **cookie_buf);
extern int credentials_externalize_with_keys(Credentials *credentials,
											 Crypt_keys *ck, char **buf);
extern int credentials_externalize(Credentials *credentials, char **buf);
extern int is_local_user_identity(Credentials *cr);

extern int make_set_cookie_header(char *cookie, char *lifetime, int for_acs,
								  int cookie_only, char **cookie_buf);
extern int make_set_void_cookie_header(char *cookie, int for_acs,
									   char **set_cookie_buf);
extern int make_set_auth_cookie_header(Credentials *credentials,
									   char *lifetime, int cookie_only,
									   char **cookie_buf);
extern char *make_auth_cookie_name(Credentials *cr);
extern char *make_cookie_name_app_prefix(const Cookie_name_terminators *term);
extern char *
	make_cookie_name_federation_prefix(const Cookie_name_terminators *term);
extern Cookie_name_terminators *init_cookie_name_terminators(char *term_str);
extern int set_cookie_name_terminators(Cookie_name_terminators *term);

extern int get_cookies(Kwv *kwv, Cookie **cookies, unsigned *ncookies);
extern void cookies_html(FILE *fp, Cookie *cookies);

extern int cookie_value_to_credentials(char *cookie_value, char *remote_addr,
									   Credentials **credentials);
extern int cookie_to_credentials(Cookie *cookie, char *remote_addr,
								 Credentials **credentials);
extern Cookie *cookie_parse(char *cookie_value, int *is_dacs_cookie);
extern int is_auth_cookie_name(char *cookie_name);
extern int set_cookie_output_syntax(Cookie_syntax syntax);
extern int configure_cookie_syntax(char *cookie_syntax, char **errmsg);
extern char *make_cookie_name(Cookie_name_terminators *term,
							  const char *app, const char *federation,
							  char *jurisdiction, char *username,
							  char *special);
extern Cookie_name *parse_cookie_name(Cookie_name_terminators *term, char *name);

extern char *get_passwd(Get_passwd_type type, void *arg);

extern char *passwd_make_digest(Digest_desc *dd, char *passwd, Pw_entry *);
extern int passwd_check_digest(Digest_desc *dd, char *given_passwd, Pw_entry *);
extern char *passwd_lookup_password_digest_name(Digest_desc *dd);
extern Digest_desc *passwd_get_digest_algorithm(const char *digest_name);

extern char *make_hash_from_credentials(Credentials *cr);

extern char *get_revocations(char *item_type);
extern Dsvec *parse_revocations(char *buf, int check_exprs);
extern int check_revocation(Credentials *c, Kwv *kwv, char *item_type,
							int for_acs);

extern Http_auth *http_auth_match_directive(char *url_path);

extern Http_auth_authorization
	*http_auth_authorization_parse(char *enc_auth_info, char **errmsg);
extern Http_auth_authorization *http_auth_authorization_init(char *username,
															 char *scheme,
															 char *realm);
extern char *http_auth_basic_auth(Http_auth *auth);
extern char *http_auth_digest_auth(Http_auth *auth, char *domain);
extern int http_digest_auth(char *username, Http_auth_authorization *aa);
extern Http_auth_www_authenticate
	*http_auth_www_authenticate_parse(char *challenge, char **errmsg);
extern int http_digest_check(Http_auth_authorization *aa,
							 char *stored_password);

extern void make_randomized_from_passphrase(unsigned char *pp,
											unsigned int pplen,
											unsigned int needed,
											unsigned char **rbuf);
extern char *auth_style_to_string(Auth_style auth_style);
extern Auth_style auth_style_from_string(const char *str);

extern int pam_auth(Kwv *, char *username, Pam_auth_tid **tidp,
					char *hostname, in_port_t port,
					char **mapped_username, char **lifetime, char **xml,
					Auth_prompts **prompts);
extern int pamd_get_block(FILE *fp, Ds *buf, Kwv **kwvp);
extern in_port_t pam_get_pamd_port(char *portname, char **errmsg);
extern Pam_auth_tid *pam_new_tid(char *reply_addr, char *reply_port);
extern Pam_auth_tid *pam_parse_tid(char *str);
extern char *make_pam_prompt_form(Auth_prompts *prompts, char *jurisdiction,
								  char *action_url, char *action_query,
								  char *inputs);
extern int count_valid_credentials(Credentials *credentials);

extern char *auth_tracker(Credentials *cr);
extern char *auth_identity(char *federation, char *jurisdiction,
						   char *username, char *tracker);
extern char *auth_identity_mine(char *username);
extern char *auth_identity_from_credentials(Credentials *cr);
extern char *auth_identity_from_credentials_track(Credentials *cr);
extern char *auth_identities_from_credentials_track(Credentials *credentials);
extern char *auth_identity_from_cookie(Cookie *c);
extern int is_dacs_admin(Credentials *credentials);
extern int is_dacs_admin_identity(char *f, char *j, char *u);
extern int reset_scredentials(Credentials *credentials);
extern int make_scredentials_cookie(Credentials *credentials, char **buf);
extern int make_set_scredentials_cookie_header(Credentials *credentials,
											   char **cookie_buf);
extern int get_valid_scredentials(Cookie *cookies, char *remote_addr,
								  int valid_for_acs,
								  Credentials **credentials,
								  Credentials **selected,
								  Scredentials **scp);
extern int get_scredentials(Cookie *cookies, Scredentials **sp);
extern int make_set_void_selected_cookie_header(char **buf);
extern int is_selected_cookie_name(char *cookie_name);

extern int is_matching_user(char *user, Credentials *credentials,
							DACS_name_cmp cmp_mode,
							Credentials **matched, char **errmsg);
extern int is_matching_user_identity(char *user, Credentials *credentials,
									 DACS_name_cmp cmp_mode, char **errmsg);

extern int auth_add_success_expr(char *expr);
extern int auth_get_success_exprs(char ***list);
extern int auth_success(Kwv *kwv, Kwv *kwv_auth);

extern char *dacs_approval_create(char *uri, char *method, char *ident,
								  char *dn, EVP_PKEY *private_key);

extern int auth_add_option(char *option_str, Kwv *kwv_options, Dsvec *options,
						   Dsvec *argv_spec);
extern int auth_get_options_from_file(char *filename, Kwv *kwv_options,
									  Dsvec *options, Dsvec *argv_spec);


/* In commonjson.c */
extern char *make_json_common_status(Common_status *status);
extern char *make_json_roles_reply(Roles_reply *rr);
extern char *make_json_auth_reply_ok(Auth_reply_ok *ok);
extern char *make_json_auth_reply_failed(char *username, char *redirect_url);
extern char *make_json_auth_reply_status(char *context, char *code,
										 char *message);
extern char *make_json_auth_reply_prompt(char *prompt);
extern int make_json_credentials(Credentials *cr, char **credentials_str);
extern char *make_json_dacs_current_credentials(Credentials *selected,
												Dsvec *dsv_activity,
												int detailed);
extern int make_json_credentials(Credentials *credentials,
								 char **credentials_str);

/* In commonxml.c */
extern char *make_xml_auth_reply_ok(Auth_reply_ok *ok);
extern char *make_xml_auth_reply_failed(char *username, char *redirect_url);
extern char *make_xml_auth_reply_error(char *context, char *code,
									   char *message);
extern char *make_xml_auth_reply_prompt(char *prompt);
extern char *make_xml_roles_reply(Roles_reply *rr);
extern char *make_xml_common_status(Common_status *status);
extern int make_xml_credentials(Credentials *credentials,
								char **credentials_str);
extern char *make_xml_dacs_current_credentials(Credentials *selected,
											   Dsvec *dsv_activity,
											   int detailed);
extern char *make_xml_root_element(char *root);
extern int make_xml_init_xmlns(void);
extern int make_xml_add_xmlns(char *ns);

extern void emit_roles_reply_ok(FILE *fp, char *role_str);
extern void emit_roles_reply_failed(FILE *fp, char *reason);

extern char *get_role_string(char *vfs_uri, char *item_type, char *username,
							 char *fs);
extern Dsvec *get_roles(char *item_type, char *username, char *fs);

/* In pamlib.c */
extern int make_json_prompts(Auth_prompts *prompts, int html, char **json);
extern int make_xml_prompts(Auth_prompts *prompts, int html, char **xml);

/* In dacspasswd.c */
extern Pw_entry *pw_init_entry(Pw_entry *, char *);
extern char *pw_make_entry(Pw_entry *pw);
extern Pw_entry *pw_parse_entry(char *username, char *stored_digest);
extern int pw_check_passwd(Vfs_handle *h, char *username, char *given_passwd,
						   Digest_desc *dd);
extern Pw_entry *pw_read_entry(Vfs_handle *h, char *username);
extern int pw_delete_entry(Vfs_handle *h, char *username);
extern int pw_exists_entry(Vfs_handle *h, char *username);
extern char *pw_getdigest_entry(Vfs_handle *h, char *username);
extern Ds *pw_getdata_entry(Vfs_handle *h, char *username);
extern int pw_test_entry(Vfs_handle *h, Pw_op op, char *username);
extern Dsvec *pw_list_entries(Vfs_handle *h);
extern int pw_add_entry(Vfs_handle *h, char *username, char *given_passwd,
						Digest_desc *dd, Pw_state new_state, Ds *data);
extern int pw_reset_entry(Vfs_handle *h, char *username, char *given_passwd,
						  Digest_desc *dd, Pw_state new_state,
						  Pw_op data_op, Ds *data);
extern int pw_rename_entry(Vfs_handle *h, char *old_username,
						   char *new_username);
extern int pw_replace_entry(Vfs_handle *h, char *username, char *given_passwd,
							Digest_desc *dd, Pw_state new_state,
							Pw_op data_op, Ds *data);
extern int pw_update_entry(Vfs_handle *h, char *username, char *given_passwd,
						   Digest_desc *dd, Pw_state new_state);
extern int pw_disable_entry(Vfs_handle *h, char *username);
extern int pw_enable_entry(Vfs_handle *h, char *username);
extern int pw_is_passwd_acceptable(char *passwd, char *constraints);
extern int pw_parse_constraints(char *constraint, Pw_constraints *conf);
extern char *pw_prompt_new_password(char *username, char *msg, char **errmsg);
extern int pw_check_username(char *username);

/* In auth_grid.c */
extern Auth_grid *auth_grid_unflatten(char *grid_str, int decrypt);
extern Dsvec *auth_grid_parse_challenge(char *challenge_str);
extern Auth_grid *auth_grid_get(char *item_type, char *username);
extern int auth_grid_verify(Auth_grid *grid, Dsvec *challenge, char *response,
							unsigned int grid_lifetime);
extern Dsvec *auth_grid_decrypt_challenge(char *ext_token,
										  unsigned int challenge_lifetime);
 
/* In dacsinfocard.c */
extern Mic_entry *mic_read(Vfs_handle *h, char *identity, char *ppid);
extern int mic_register_entry(Vfs_handle *h, char *identity, char *ppid,
							  Dsvec *claims, Ic_use_mode use_mode,
							  Mic_sts_auth *sts_auth, Ic_state state);
extern Ic_config *ic_config(void);
extern Ic_auth *ic_lookup_entry(Vfs_handle *h, char *xmlToken, Ic_config *conf);
extern Dsvec *ic_get_config_audience(void);
extern int ic_get_digest_algorithm(char **digest_name, Digest_desc *desc);
extern Ic_sts_authtype ic_lookup_sts_authtype(char *authtype_str);
extern int ic_lookup_sts_authtype_str(Ic_sts_authtype authtype,
									  char **short_str, char **long_str);

/* In auth_roles.c */
extern Acs_expr_result auth_eval(char *expr, Kwv *kwv, Kwv *kwv_auth,
								 Kwv *kwv_options, char **result_str);
extern Roles_module *roles_module_lookup(Roles_module_info *rmi, char *id);
extern Roles_module_info *
auth_parse_roles_clause_init(Roles_module_info *o_rmi);
extern Roles_module_info *auth_parse_roles_clauses(Roles_module_info *o_rmi);
extern int auth_process_roles_clause(Roles_module *m, char *username,
									 char *jurisdiction, Kwv *kwv,
									 Kwv *kwv_auth, char **role_str,
									 Common_status *common_status,
									 char **errmsg);
extern int roles_module_invoke(Roles_module *m, char *username, char *passwd,
							   char *jurisdiction, Kwv *kwv, Kwv *kwv_auth,
							   char **role_str, Common_status *common_status,
							   char **errmsg);
extern int collect_roles(char *username, char *jurisdiction, Kwv *kwv,
						 Kwv *kwv_auth, Ds **ds_roles,
						 Common_status *common_status,
						 Auth_failure_reason *failure_reason);


/* In auth_token.c */
extern char *auth_token(char *digest_name, unsigned char *key,
						unsigned int klen, unsigned char *value,
						unsigned int vlen, unsigned int ndigits,
						unsigned int base);
extern char *auth_hotp_value(unsigned char *key, unsigned int klen,
							 unsigned char *value, unsigned int vlen,
							 unsigned int ndigits, unsigned int base);
extern char *auth_totp_value(char *digest_name, unsigned char *key,
							 unsigned int klen, time_t *clock_val,
							 unsigned int time_step, int drift_adj,
							 unsigned int ndigits, unsigned int base,
							 char **mfp);
extern void auth_token_inc_counter(unsigned char *counter);
extern int auth_token_current(Auth_token *token, char **hvalp,
							  char **moving_factorp);
extern int auth_token_validate(Auth_token *token, char *otp_value,
							   char *pin, Token_pin_mode pin_mode,
							   char *challenge, unsigned int window);
extern int auth_hotp_token_validate(Auth_token *token, char *otp_value,
									char *pin, Token_pin_mode pin_mode,
									unsigned int window);
extern int auth_totp_token_validate(Auth_token *token, char *otp_value,
									char *pin, Token_pin_mode pin_mode,
									unsigned int time_step,
									int base_window_delta,
									unsigned int drift_window,
									unsigned int ndigits, unsigned int base,
									int *driftp);
extern Auth_token *auth_token_get(char *item_type, char *username);
extern int auth_token_update(Auth_token *token);


/* Local authentication modules */
#ifdef ENABLE_APACHE_AUTH
extern int local_apache_auth(char *username, char *password, char *aux,
							 Http_auth_authorization *aa,
							 Apache_module module, Apache_dbm dbm, char *path);
#endif

#ifdef ENABLE_CAS_AUTH
extern int local_cas_auth(char *username, char *password, char *aux,
						  Cas_auth *cas_auth);
#endif

#ifdef ENABLE_TGMA_AUTH
extern int local_tgma_auth(char *username, char *password, char *aux,
						  Tgma_auth *tgma_auth);
#endif

#ifdef ENABLE_GRID_AUTH
extern int local_grid_auth(char *username, char *password, char *aux);
#endif

#ifdef ENABLE_HTTP_AUTH
extern int local_http_auth(char *username, char *password, char *aux,
						   Url_auth *url_auth, Auth_reply **auth_reply);
#endif

#ifdef ENABLE_INFOCARD_AUTH
extern int local_infocard_auth(char *xmlToken, char *aux, Ic_auth *ic);
#endif

#ifdef ENABLE_LDAP_AUTH
extern int local_ldap_auth_by_dn(Uri *url, char *username, char *password,
								 struct timeval *timeout, Dsvec *avas);
extern int local_ldap_auth_by_attr(Uri *admin_url, char *admin_password,
								   char *root_dn, char *filter, char *password,
								   struct timeval *timeout, Dsvec *avas);
#endif
  
#ifdef ENABLE_NTLM_AUTH
extern int local_ntlm_auth(char *username, char *password, char *aux,
						   int smb_port, char *smb_server, char *smb_domain);
#endif

#ifdef ENABLE_PAM_AUTH
extern int local_pam_auth(Kwv *kwv_trans, char *username,
						  char *hostname, in_port_t port,
						  char **mapped_username, char **lifetime, char **xml,
						  Pam_auth_tid **tidp, Auth_prompts **prompts);
#endif

#ifdef ENABLE_PASSWD_AUTH
extern int local_passwd_auth(char *username, char *given_passwd, char *aux);
#endif

#ifdef ENABLE_SIMPLE_AUTH
extern int local_simple_auth(char *username, char *password, char *aux);
#endif

#ifdef ENABLE_TOKEN_AUTH
extern int local_token_auth(char *username, char *password, char *aux,
						   int accept_window);
#endif

#ifdef ENABLE_UNIX_AUTH
extern int local_unix_auth(char *username, char *password, char *aux);
extern int local_unix_pam_auth(char *pam_service, char *username,
							   char *password, char *aux);
#endif

/* Local roles modules */
extern int local_roles(char *username, char **role_str);

#ifdef ENABLE_UNIX_ROLES
extern int local_unix_roles(char *username, char **role_str);
#endif

extern char *user_info_service_uri(char *jurisdiction_name);
extern int parse_xml_user_info(char *user_info_rec, User_info **uip);
extern Dsvec *user_info_load(char *jurisdiction);
extern Dsvec *user_info_active(Dsvec *dsv, char *ident);
extern Dsvec *user_info_last_auth(Dsvec *dsv, char *ident);

#ifdef ENABLE_TGMA_AUTH
extern void tgma_format_form_hidden(Ds *ds, char *name, char *value);
extern Ds *tgma_format_form_vars(char *username, char *jurisdiction,
								 Tgma_auth *tgma_auth);
extern char *tgma_form_hmac(Ds *ds);
extern char *tgma_iid_hash(const char *iid);
extern int tgma_tcp_read(int sd, unsigned char *buf, size_t *buflen,
						 unsigned int timeout_secs);
extern int tgma_tcp_write(int sd, unsigned char *buf, size_t buflen);
extern int tgma_send(int sd,  struct sockaddr_in *to, unsigned char *datap,
					 size_t datalen);
extern int tgma_recv(int sd, int max_secs, unsigned char *bufp, size_t *buflen,
					 struct sockaddr *from, socklen_t *fromlen);
extern char *tgma_hmac_result(Ds *hkey, Ds *str);
extern char *tgma_make_iid(void);
extern int tgma_request(struct sockaddr_in *tgma_addr, char *username,
						char *jurisdiction, char *iid, int use_tcp,
						unsigned int tgma_window_secs);
#endif

#ifdef ENABLE_USER_INFO
extern void user_info_authenticate(Credentials *cr);
extern void user_info_signout(Credentials *cr);
extern void user_info_access(Credentials *cr, char *uri,
							 char *remote_addr, char *remote_host);
#endif

#ifdef __cplusplus
}
#endif

#endif
