/* $Id: sfsauth_prot.x,v 1.3 2001/11/19 06:02:03 dm Exp $ */

/*
 * This file was written by David Mazieres.  Its contents is
 * uncopyrighted and in the public domain.  Of course, standards of
 * academic honesty nonetheless prevent anyone in research from
 * falsely claiming credit for this work.
 */

%#include "sfs_prot.h"

typedef string sfsauth_errmsg<>;


/*
 * sfs_authreq2 -- Contents of the login certificate in sfs_loginarg
 */
struct sfs_authreq2 {
  sfs_msgtype type;		/* = SFS_SIGNED_AUTHREQ */
  sfs_hash authid;		/* SHA-1 (sfs_authinfo) */
  sfs_seqno seqno;		/* Counter, value unique per authid */
  sfs_idname user;		/* User name, can be "" for sigauth */
};
struct sfs_sigauth {
  sfs_authreq2 req;
  sfs_sig sig;
};
struct sfs_unixpwauth {
  sfs_authreq2 req;
  string password<>;
};
struct sfs_srpauth {
  sfs_authreq2 req;
  opaque msg<>;
};
union sfs_autharg2 switch (sfs_authtype type) {
 case SFS_AUTHREQ:
   sfs_sigauth sigauth;
 case SFS_UNIXPWAUTH:
   sfs_unixpwauth pwauth;
 case SFS_SRPAUTH:
   sfs_srpauth srpauth;
};

struct sfsauth2_loginarg {
  sfs_loginarg arg;
  sfs_hash authid;
  string source<>;		/* Source of request, for audit trail */
};

struct sfsauth2_loginokres {
  sfsauth_cred creds<>;
  opaque resmore<>;		/* If necessary, for mutual authentication */
  string hello<>;		/* To be printed on user's terminal */
};
union sfsauth2_loginres switch (sfs_loginstat status) {
 case SFSLOGIN_OK:
   sfsauth2_loginokres resok;
 case SFSLOGIN_MORE:
   opaque resmore<>;
 case SFSLOGIN_BAD:
   sfsauth_errmsg errmsg;
 default:
   void;
};


/*
 * Auth server database types
 */
%const u_int32_t sfsauth_noid = 0xffffffff;
struct sfsauth_userinfo {
  sfs_idname name;
  unsigned id;
  unsigned vers;
  unsigned gid;
  sfs_idname *owner;
  sfs_pubkey pubkey;
  string privs<>;
  string pwauth<>;		/* Never returned, only set */
  opaque privkey<>;
  string audit<>;
};
struct sfsauth_groupinfo {
  sfs_idname name;
  unsigned id;
  unsigned vers;
  sfs_idname owners<>;
  sfs_idname members<>;
  string audit<>;
};
struct sfsauth_ids {
  sfs_idname user;
  unsigned uid;
  unsigned gid;
  unsigned gidlist<>;
};
struct sfsauth_srpparms {
  unsigned pwcost;
  string parms<>;
};
enum sfsauth_dbtype {
  SFSAUTH_ERROR = 0,
  SFSAUTH_USER = 1,
  SFSAUTH_GROUP = 2,
  SFSAUTH_IDS = 3,
  SFSAUTH_SRPPARMS = 5
};
union sfsauth_dbrec switch (sfsauth_dbtype type) {
 case SFSAUTH_ERROR:
   sfsauth_errmsg errmsg;
 case SFSAUTH_USER:
   sfsauth_userinfo userinfo;
 case SFSAUTH_GROUP:
   sfsauth_groupinfo groupinfo;
 case SFSAUTH_IDS:
   sfsauth_ids ids;
 case SFSAUTH_SRPPARMS:
   sfsauth_srpparms srpparms;
};

enum sfsauth_dbkeytype {
  SFSAUTH_DBKEY_NULL = 0,
  SFSAUTH_DBKEY_NAME = 1,
  SFSAUTH_DBKEY_ID = 2,
  SFSAUTH_DBKEY_PUBKEY = 3
};
union sfsauth_dbkey switch (sfsauth_dbkeytype type) {
 case SFSAUTH_DBKEY_NULL:
   void;
 case SFSAUTH_DBKEY_NAME:
   sfs_idname name;
 case SFSAUTH_DBKEY_ID:
   unsigned id;
 case SFSAUTH_DBKEY_PUBKEY:
   sfs_pubkey key;
};

/* arg must be accompanied by an authuint to retrieve certain fields. */
struct sfsauth2_query_arg {
  sfsauth_dbtype type;
  sfsauth_dbkey key;
};
typedef sfsauth_dbrec sfsauth2_query_res;


/* 
 * Signed message required for an update
 */
struct sfs_updatereq {
  sfs_msgtype type;		/* = SFS_UPDATEREQ */
  sfsauth_dbrec rec;		/* USER or GROUP only */
};

/* Arg must be accompanied by authuint. */
struct sfsauth2_update_arg {
  sfs_updatereq req;
  sfs_sig *newsig;		/* sig by req.rec.userinfo->pubkey if
				 * non admin user updating key. */
  sfs_sig *authsig;		/* Signature for key corresponding to
				 * authuint.  Can be empty when
				 * registering. */
};
union sfsauth2_update_res switch (bool ok) {
 case false:
   sfsauth_errmsg errmsg;
 case true:
   void;
};


program SFSAUTH_PROG {
	version SFSAUTH_V2 {
		void
		SFSAUTH2_NULL (void) = 0;

		sfsauth2_loginres
		SFSAUTH2_LOGIN (sfsauth2_loginarg) = 1;

		sfsauth2_query_res
		SFSAUTH2_QUERY (sfsauth2_query_arg) = 2;

		sfsauth2_update_res
		SFSAUTH2_UPDATE (sfsauth2_update_arg) = 3;
	} = 2;
} = 344442;
