////////////////////////////////////////////////////////////
//
//	Declaration of a class
//	DceCallee
//
//      Copyright 2001 
//
////////////////////////////////////////////////////////////

#ifndef __DCECALLEE_H__
#define __DCECALLEE_H__


#include <dce/rpc.h>
#include <dce/id_base.h>
#include <dce/sec_cred.h>

const int CLIENT_PRINCIPAL_NAME_SIZE = 1023;


	// DceCalleeSecurityData
	// used by DceCallee internally
	
struct DceCalleeSecurityData
{
	
	unsigned_char_t *server_principal_name;
	unsigned32 	protection_level,
			authentication_service,
			authorization_service; 
	rpc_authz_cred_handle_t callers_identity;
			
	DceCalleeSecurityData():
	server_principal_name(0),
	protection_level(0),
	authentication_service(0),
	authorization_service(0)
	{}
	
	~DceCalleeSecurityData()
	{ unsigned32 s; rpc_string_free(&server_principal_name,&s); }
	
}; 

	// DceCalleeOption

struct DceCalleeOption
{
	unsigned32 	protection_level,
			authentication_service,
			authorization_service; 
			
	DceCalleeOption():
	protection_level(rpc_c_protect_level_none),
	authentication_service(rpc_c_authn_none),
	authorization_service(rpc_c_authz_none)
	{}

};

	// DceCalleeReport
	// any securyty layer can set "authorized" to false

struct DceCalleeReport
{
	// a pair of zero terminated strings
	char 	client_principal_name[CLIENT_PRINCIPAL_NAME_SIZE+1],
		*client_principal_name_overflow;
		
	bool	authorized; 
			
	DceCalleeReport():
	client_principal_name_overflow(0),
	authorized(true)		
	{client_principal_name[0]=0;}
	~DceCalleeReport()
	{ delete client_principal_name_overflow; }
	
	int set_name(unsigned_char_t * );

};


	// DceCallee
	// security handler

class DceCallee
{
DceCallee(const DceCallee&);
DceCallee& operator=(const DceCallee&);
public:
	DceCallee();
	~DceCallee();
	
	// checked if set
	int set_server_principal_name(const char *z);
	
	
	// defualt is true
	int run_level1_check(bool z)
	{ level1_check=z; return 0;}
	
	// defualt is true
	int run_level2_check(bool z)
	{ level2_check=z; return 0;}
	
	// up to 10 such options
	int allow_option(const DceCalleeOption& z);
		
	void start_dce_response(handle_t binding_habdle,DceCalleeReport& report,error_status_t *rpc_error_status);

protected:

	bool level1_check,level2_check;
	unsigned_char_t *server_principal_name;
	DceCalleeOption options[10];
	int option_count;
		
	// true - passed 
	virtual bool check_client_principal_name(const char * )
	{return true;}
		
	// sets security_data
	void check_level1(DceCalleeSecurityData& security_data,DceCalleeReport& report);		
	
	virtual void check_level2(handle_t ,DceCalleeSecurityData&,DceCalleeReport&,error_status_t *rpc_error_status)
	{*rpc_error_status=rpc_s_ok; }
	
	// default implementation writes to stdout
	// provide a custom logging function, if needed
	virtual int dce_log(const char *message, error_status_t status);

		
};



#endif

/*
	A declaration of an interface's functionality and security
	in a file1.h
	
	class SomeImplementation
	{ 
	public:
	int set(...);
	int fun(int z);
	private:
		data, mutexes
	};
	
	class SomeSecurity:public DceCallee
	{
	public:
	int set(...);
	void security_check(handle_t binding_handle,const DceCalleeSecurityData,error_status_t *rpc_error_status);
	private:
		data, mutexes
	}
	
	An implementation of an interface's functionality and security
	in a file1.C:
	
	int SomeImplementation::fun(int z)
	{
		use data (do not change it)
	}
	
	void SomeSecurity::security_check(handle_t h,const DceCalleeSecurityData& z,error_status_t *s)
	{
		use data (do not change it)
	}
	
	A formal implementation of an interface on a file2.C:
	
	extern SomeSecurity *some_security;
	extern SomeImplementation *some_implementation;
	
	int fun(handle_t binding_handle,int z,error_status_t *rpc_error_status) - global function
	{
	DceCalleeReport report;
	some_security->start_dce_response(binding_handle,report,rpc_error_status)
	if(rpc_error_status!=rpc_s_ok) return -1;
	return some_implementation->fun(z);
	}
	
	A setup in a main function:
	
	SomeSecurity *some_security;
	SomeImplementation *some_implementation;
	
	int main()
	{
		SomeSecurity z;
		some_security=&z;
		some_security->set(...);
		
		SomeImplementation zz;
		some_implementation=&zz;
		some_implementation->set(...);
		
	}
	
*/