/*
 * Copyright (C) 1998 Netscape Communications Corporation.
 * All Rights Reserved.
 *
 * Copyright 2016 Red Hat, Inc. and/or its affiliates.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#ifndef __SVRCORE_H_
#define __SVRCORE_H_

#include <prtypes.h>
#include <seccomon.h>
#include <pk11func.h>

PR_BEGIN_EXTERN_C
/* ------------------------------------------------------------ */
/*
 * SVRCOREError - error values generated by components in the
 *   SVRCORE module.
 */
enum SVRCOREError
{
  SVRCORE_Success                  = 0,
  SVRCORE_NoMemory_Error           = 1,
  SVRCORE_System_Error             = 2,
  SVRCORE_NoSuchToken_Error        = 3,
  SVRCORE_IncorrectPassword_Error  = 4,
  SVRCORE_IOOperationError         = 5,
  SVRCORE_SocketError              = 6,
  SVRCORE_PermissionError          = 7,
  SVRCORE_ClockError               = 8,
  SVRCORE_TimeoutError             = 9,
  SVRCORE_MissingFeature           = 10,
  SVRCORE_MaximumErrorValue        = 10
};
typedef enum SVRCOREError SVRCOREError;


/* ------------------------------------------------------------ */
/*
 * PIN Object - provides an interface to get the PIN for
 *   a PKCS11 token.
 *
 * Methods:
 *   destroyObj - delete the object
 *   getPin - retrieve the PIN for the token with name "tokenName".  The
 *     retry flag is set if this request is a retry due to an incorrect
 *     PIN.  Implementations should not return a "cached" copy in this case,
 *     since it will result in multiple fails, and will disable some tokens.
 *     The memory allocated for the returned string must be on the system
 *     heap.  It will be released using "free"
 */
typedef struct SVRCOREPinObj SVRCOREPinObj;
typedef struct SVRCOREPinMethods SVRCOREPinMethods;
struct SVRCOREPinMethods
{
  void *(*reserved0)(SVRCOREPinObj *, void *);
  void  (*reserved1)(SVRCOREPinObj *);
  void  (*destroyObj)(SVRCOREPinObj* obj);
  char *(*getPin)(SVRCOREPinObj *obj, const char *tokenName, PRBool retryFlag);
};

struct SVRCOREPinObj
{
  const SVRCOREPinMethods *methods;
};

/*
 * Methods on SVRCOREPinObj
 */
/* char *SVRCORE_GetPin(SVRCOREPinObj *, char *tokenName, PRBool retry) */
#define SVRCORE_GetPin(obj, name, retry) \
  (obj)->methods->getPin(obj, name, retry)

/* void SVRCORE_DestroyPinObj(SVRCOREPinObj *) */
#define SVRCORE_DestroyPinObj(obj) \
  (obj)->methods->destroyObj(obj)


/* ------------------------------------------------------------ */
/*
 * SVRCORE_RegisterPinObj - registers the PIN handling object with the
 *   PK11 module.
 * 
 * The PIN object's getPin method will be called when the NSS layer
 * requires a password/PIN for a token.  The caller may provide NULL
 * as the pin object, in which case, no password callbacks will be invoked.
 * This may be used to unregister the object prior to deleting it.
 */
void
SVRCORE_RegisterPinObj(SVRCOREPinObj *obj);

/*
 * SVRCORE_GetRegisteredPinObj - get the currently registered Pin object
 *  (if any)
 *
 * Return a pointer to the currently register Pin object.  If none has been
 * registered, NULL is returned.
 */
SVRCOREPinObj *
SVRCORE_GetRegisteredPinObj(void);

/* 
 *  SVRCORE_DestroyRegisteredPinObj - Destroys (frees) the currently registered
 * pin object, and zeros the pointer. This way a new object can be created
 */
void
SVRCORE_DestroyRegisteredPinObj(void);

/* ------------------------------------------------------------ */
/*
 * SVRCOREStdPinObj - implementation of SVRCOREPinObj that
 *   provides the standard handling for servers.  This includes
 *   optional file lookup, and optional caching
 *
 * SVRCORE_SetStdPinInteractive - allows the application to declare
 *   that input via the terminal is no longer possible (set interactive
 *   to PR_FALSE).  See the corresponding routine for UserPinObj
 *
 * SVRCORE_StdPinGetPin - get a (securely) cached PIN value.  Returns
 *   SVRCORE_NoSuchToken_Error if the object is not set up for caching.
 */
typedef struct SVRCOREStdPinObj SVRCOREStdPinObj;

SVRCOREError
SVRCORE_CreateStdPinObj(SVRCOREStdPinObj **out,
  const char *filename, PRBool cachePINs);

void
SVRCORE_SetStdPinInteractive(SVRCOREStdPinObj *obj, PRBool interactive);

SVRCOREError
SVRCORE_StdPinGetPin(char **pin, SVRCOREStdPinObj *obj,
  const char *tokenName);

void
SVRCORE_DestroyStdPinObj(SVRCOREStdPinObj *obj);

/* ------------------------------------------------------------ */
/*
 * SVRCOREUserPinObj - implementation of SVRCOREPinObj that
 *    requests the PIN on the terminal.
 *
 * SVRCORE_SetUserPinInteractive - allows the application to declare
 *   that input via the terminal is no longer possible (set interactive
 *   to PR_FALSE).  When this is the case, the object returns NULL (no
 *   PIN available)
 */
typedef struct SVRCOREUserPinObj SVRCOREUserPinObj;

SVRCOREError
SVRCORE_CreateUserPinObj(SVRCOREUserPinObj **out);

void
SVRCORE_SetUserPinInteractive(SVRCOREUserPinObj *obj, PRBool interactive);

void
SVRCORE_DestroyUserPinObj(SVRCOREUserPinObj *obj);

/* ------------------------------------------------------------ */
/*
 * SVRCOREAltPinObj - allows cascading of PinObj.  For example, an
 *   application can first check a file (FilePinObj) and then the terminal
 *   (UserPinObj).  The primary object is called first then, if no PIN is
 *   available, the alternate object is called.
 *
 *   This object does not claim ownership of the PinObjs.  The application
 *   must delete them (after deleting the AltPinObj).
 */
typedef struct SVRCOREAltPinObj SVRCOREAltPinObj;

SVRCOREError
SVRCORE_CreateAltPinObj(
  SVRCOREAltPinObj **out,
  SVRCOREPinObj *primary, SVRCOREPinObj *alt);

void SVRCORE_DestroyAltPinObj(SVRCOREAltPinObj *obj);

/* ------------------------------------------------------------ */
/*
 * SVRCOREFilePinObj - implements reading PINs from a file.  The
 *   name of the file is provided in the constructor.
 */
typedef struct SVRCOREFilePinObj SVRCOREFilePinObj;

SVRCOREError
SVRCORE_CreateFilePinObj(
  SVRCOREFilePinObj **out,
  const char *filename);

void
SVRCORE_DestroyFilePinObj(SVRCOREFilePinObj *obj);

/* ------------------------------------------------------------ */
/*
 * SVRCORECachedPinObj - implementation of SVRCOREPinObj that
 *    caches the PIN in a secure way.
 *
 * SVRCORE_CachedPinGetPin - allows the application to retrieve
 *   the stored pin.  The application should free the value useing free()
 *   after clearing the memory.
 */
typedef struct SVRCORECachedPinObj SVRCORECachedPinObj;

SVRCOREError
SVRCORE_CreateCachedPinObj(SVRCORECachedPinObj **out, SVRCOREPinObj *alt);

SVRCOREError
SVRCORE_CachedPinGetPin(char **pin, SVRCORECachedPinObj *obj,
  const char *tokenName);

void
SVRCORE_DestroyCachedPinObj(SVRCORECachedPinObj *obj);


/* ------------------------------------------------------------ */
/*
 * SVRCORESystemdPinObj - implementation of SVRCOREPinObj that
 *      is able to contact the systemd ask pass api to retrieve
 *      the PIN material.
 */

typedef struct SVRCORESystemdPinObj SVRCORESystemdPinObj;

SVRCOREError
SVRCORE_CreateSystemdPinObj(SVRCORESystemdPinObj **out, uint64_t timeout);

void
SVRCORE_DestroySystemdPinObj(SVRCORESystemdPinObj *obj);

/* ------------------------------------------------------------ */
/*
 * SVRCOREStdSystemdPinObj - implementation of SVRCOREPinObj that
 *   provides the standard handling for servers, including systemd.
 *   This includes systemd request, optional file lookup, and
 *   optional caching.
 *
 * SVRCORE_SetStdSystemdPinInteractive - allows the application to declare
 *   that input via the terminal is no longer possible (set interactive
 *   to PR_FALSE).  See the corresponding routine for UserPinObj
 *
 * SVRCORE_StdSystemdPinGetPin - get a (securely) cached PIN value.  Returns
 *   SVRCORE_NoSuchToken_Error if the object is not set up for caching.
 */
typedef struct SVRCOREStdSystemdPinObj SVRCOREStdSystemdPinObj;

SVRCOREError
SVRCORE_CreateStdSystemdPinObj(SVRCOREStdSystemdPinObj **out,
  const char *filename, PRBool cachePINs, PRBool systemdPINs, uint64_t timeout);

void
SVRCORE_SetStdSystemdPinInteractive(SVRCOREStdSystemdPinObj *obj, PRBool interactive);

SVRCOREError
SVRCORE_StdSystemdPinGetPin(char **pin, SVRCOREStdSystemdPinObj *obj,
  const char *tokenName);

void
SVRCORE_DestroyStdSystemdPinObj(SVRCOREStdSystemdPinObj *obj);

/* ------------------------------------------------------------ */
/*
 * Implements SVRCORESecurePinStore interface
 */
typedef struct SVRCOREPk11PinStore SVRCOREPk11PinStore;

/*
 * SVRCORE_GetPk11PinStoreError
 */
SECStatus SVRCORE_Pk11StoreGetError(const SVRCOREPk11PinStore *store);

/* Experimental */
const char *SVRCORE_Pk11StoreGetMechName(const SVRCOREPk11PinStore *store);

/*
 * SVRCORE_CreatePk11PinStore
 * Args:
 *   None
 * Errors:
 *   SVRCORE_Success
 *   SVRCORE_NoMemory_Error
 *   SVRCORE_NoSuchToken_Error
 *   SVRCORE_System_Error
 *   SVRCORE_IncorrectPassword_Error
 */
SVRCOREError
SVRCORE_CreatePk11PinStore(
  SVRCOREPk11PinStore **out,  /* Output */
  const char *tokenName,
  const char *pin);

SVRCOREError
SVRCORE_Pk11StoreGetPin(
  char **out,                /* Output */
  SVRCOREPk11PinStore *store);

void
SVRCORE_DestroyPk11PinStore(
  SVRCOREPk11PinStore *store);


PR_END_EXTERN_C

#endif
