/* authserv.h -- sample authentication server internal API version 1.0
 *
 * BSD+ License  <http://access1.sun.com/codesamples/BSD.html>
 *
 * Copyright (c) 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * o  Redistribution of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * o  Redistribution in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or 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 "AS IS," without a warranty of any
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT
 * BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO
 * EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE,
 * PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE
 * THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE
 * THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or
 * intended for use in the design, construction, operation or
 * maintenance of any nuclear facility.
 *
 *  Contributor(s): Chris Newman <chris.newman@sun.com>
 *
 ************************************************************************/

/* Structure to describe a variable-sized memory object with destructor
 * callback.
 */
struct memobj {
    void (*destruct)(void *me);
    char data[1];
};

/* data used sent back to Internet Server from Authentication Server
 *  authname:      UTF-8 authentication name (for administrative proxy)
 *  username:      UTF-8 username to replay if in proxy mode
 *  password:      UTF-8 password to replay if in proxy mode
 *  version:       version of this data structure (REPLYDATA_VERSION)
 *  sasllen:       length of SASL data to send to client
 *  sasldata:      raw SASL data to send to client (not base64-encoded)
 *  authcontinue:  when non-NULL, continue authentication with another step
 *  orig_user:     UTF-8 user name extracted from client's sasldata
 *  orig_authz:    UTF-8 authentication name from client's sasldata
 */
struct replydata {
    char *authname;
    char *username;
    char *password;
    int version;

    /* added for version 2: */
    int sasllen;
    char *sasldata;
    struct memobj *authcontinue;
    char *orig_user;
    char *orig_authz;
};
#define REPLYDATA_VERSION  2

/* for backward compatibility with version one:
 */
#define REPLAYDATA_VERSION REPLYDATA_VERSION
#define replaydata replydata

/* authentication data as passed to API
 *
 *  sasl_mech:  mechanism as defined by RFC 2222 (uppercase) and registered
 *              at http://www.iana.org/assignments/sasl-mechanisms
 *  authname:   UTF-8 authentication name (for administrative proxy)
 *  username:   UTF-8 username, maximum length 256 octets
 *  password:   UTF-8 password, maximum length 256 octets
 *  service:    Service name from
 *              http://www.iana.org/assignments/gssapi-service-names
 *  localaddr:  address to which the user's client connected when requesting
 *              authentication be performed.  Not necessarily the address
 *              the server used to connect to the auth server due the
 *              possibility of multiple TCP/IP interfaces.
 *              Syntax is below.
 *  remoteaddr: address of client requesting authentication.  Syntax below.
 *  lang:       RFC 3066 language tag, NULL implies "i-default"
 *  priv:       reserved for internal use
 *  laddr:      predigested sockaddr for localaddr
 *  laddrsz:    size of laddr
 *  raddr:      predigested sockaddr for remoteaddr
 *  raddrsz:    size of raddr
 *  seclevel:   security strength factor of client/server connection
 *              0 = no connection security
 *              1 = integrity protection only
 *              40/56/64 = export crippled weak encryption
 *              112/128/168 = traditional encryption key strength
 *              256/512 = large AES keys
 *  version:    version of authdata structure, will increment as
 *              more fields are added to end.
 *  sasllen:    length of SASL data from client
 *  sasldata:   decoded data from client for arbitrary SASL mechanism
 *  authcontinue: if non-NULL, this is context from previous replydata
 *
 * RFC 2234 syntax with symbols from Appendix A (Core) and RFC 2821
 *
 *  port       = 1*5DIGIT ; values from 0 to 65535
 *  addrlit    = IPv4-address-literal / IPv6-address-literal
 *  localaddr  = addrlit SP port
 *  remoteaddr = addrlit SP port
 */
struct authdata {
    char *saslmech;
    char *authname;
    char *username;
    char *password;
    char *service;
    char *localaddr;
    char *remoteaddr;
    char *lang;
    void *spare[8];
    void *priv;
    struct sockaddr *laddr, *raddr;
    int laddrsz, raddrsz;
    int seclevel, flags;
    int version;

    /* callback to indicate successful authentication
     *  adat         this data structure
     *  replayuser   username to replay, if this is a pure proxy
     *  replaypass   password to replay, if this is a pure proxy
     */
    void (*auth_success)(const struct authdata *adat,
			 const struct replydata *rdat);

    /* callback to indicate authentication failed
     *  adat         this data structure
     *  errcode      an error code from the SASL_* table listed below
     *  errlang      RFC 3066 language tag for error text below
     *               pass NULL for i-default
     *  errtext      UTF-8 text of error message suitable for human display
     *               must not contain CR or LF.  Pass NULL for default
     *               authentication error text based on errcode.
     */
    void (*auth_fail)(const struct authdata *adat,
		      int errcode,
		      const char *errlang,
		      const char *errtext);

    /* callback to get an LDAP-style attribute
     *  if numvals is NULL, will only succeed if exactly one value
     *                      is present.
     *  returns a list of values or NULL.
     */
    const char **(*get_attr)(const struct authdata *adat,
			     const char *attrname,
			     unsigned *numvals);

    /* callback to set an LDAP-style attribute to pass back on success
     *  the actual values are copied into an internal data structure,
     *  so it is not necessary for the caller to preserve the values.
     *  a reference to the attrname may be kept and thus attrname must
     *  persist until auth_success or auth_fail is called
     *
     * returns -1 on failure, 0 on success.
     */
    int (*set_attr)(const struct authdata *adat,
		    const char *attrname,
		    const char **values,
		    unsigned numvals);

    /* end of VERSION 1 data */

    /* begin VERSION 2 data */
    unsigned sasllen;
    char *sasldata;
    struct memobj *authcontinue;
};
#define AUTHDATA_VERSION 2


/* optional header for context returned by authdat_init
 *  id:        set to AUTHHEAD_ID
 *  version:   set to AUTHHEAD_VERSION
 *  mechlist:  set to NULL terminated array of SASL mechanism names supported
 */
struct authhead {
    int id;
    int version;
    const char **mechlist;
};
#define AUTHHEAD_ID      4937502
#define AUTHHEAD_VERSION 1


/* initialize authentication data handler
 * called once for the entire process
 * returns -1 on failure, 0 on success
 * context is set to the context that will be passed to authdat_handler.
 * any read-write values in context must be protected by a mutex for
 *  thread-safety.
 */
int authdat_init(void **context);

/* this is a thread-safe handler for authentication data
 * it should not access global or static variables, unless
 * proper precautions for thread-safety are taken.
 * This is expected to call either the auth_success or the auth_fail
 * callback.
 */
void authdat_handler(void *context, const struct authdata *adat);

/* error codes from SASL API */
#ifndef SASL_FAIL
#define SASL_CONTINUE    1   /* another step is needed in authentication */
#define SASL_OK          0   /* successful result */
#define SASL_FAIL       -1   /* generic failure */
#define SASL_NOMEM      -2   /* memory shortage failure */
#define SASL_BUFOVER    -3   /* overflowed buffer */
#define SASL_NOMECH     -4   /* mechanism not supported */
#define SASL_BADPROT    -5   /* bad protocol / cancel */
#define SASL_NOTDONE    -6   /* can't request info until later in exchange */
#define SASL_BADPARAM   -7   /* invalid parameter supplied */
#define SASL_TRYAGAIN   -8   /* transient failure (e.g., weak key) */
#define SASL_BADMAC     -9   /* integrity check failed */
#define SASL_BADAUTH    -13  /* authentication failure */
#define SASL_NOAUTHZ    -14  /* authorization failure */
#define SASL_TOOWEAK    -15  /* mechanism too weak for this user */
#define SASL_ENCRYPT    -16  /* encryption needed to use mechanism */
#define SASL_TRANS      -17  /* One time use of a plaintext password will
                                enable requested mechanism for user */
#define SASL_EXPIRED    -18  /* passphrase expired, has to be reset */
#define SASL_DISABLED   -19  /* account disabled */
#define SASL_NOUSER     -20  /* user not found */
#define SASL_BADVERS    -23  /* version mismatch with plug-in */
#define SASL_UNAVAIL    -24  /* remote authentication server unavailable */
#define SASL_NOVERIFY   -26  /* user exists, but no verifier for user */
#endif
