////////////////////////////////////////////////////////////
//
// Implementation of a class
// DceCallee
//
// Copyright 2001
//
////////////////////////////////////////////////////////////
#include <string.h>
#include <stdio.h>
#include <dce/dce_error.h>
#include <dce/binding.h>
#include <dce/pgo.h>
#include "DceCallee.h"
#define OUT stdout
const int CLIENT_PRINCIPAL_NAME_MAX_SIZE = 10000;
// DceCalleeReport
int DceCalleeReport::set_name(unsigned_char_t * z)
{
if(!z) return 0;
strncpy(client_principal_name,(char*)z,CLIENT_PRINCIPAL_NAME_SIZE);
int len = strlen((char*) z);
if(len <= CLIENT_PRINCIPAL_NAME_SIZE) return 0;
if( len > CLIENT_PRINCIPAL_NAME_MAX_SIZE) return 2;
client_principal_name_overflow = new char[len - CLIENT_PRINCIPAL_NAME_SIZE +1];
strcpy(client_principal_name_overflow,(char*)z + CLIENT_PRINCIPAL_NAME_SIZE);
return 0;
}
// DceCallee
DceCallee::DceCallee():
level1_check(true),
level2_check(true),
server_principal_name(0),
option_count(0)
{
}
DceCallee::~DceCallee()
{
delete server_principal_name;
}
int DceCallee::set_server_principal_name(const char *name)
{
if(!name) return 1;
delete server_principal_name; server_principal_name=0;
int size = strlen( name ) + 1 ;
server_principal_name = new unsigned_char_t[ size ];
strcpy((char *)server_principal_name,name);
return 0;
}
int DceCallee::allow_option(const DceCalleeOption& z)
{
if(option_count>=10) return 1;
options[option_count++]=z;
return 0;
}
void DceCallee::check_level1(DceCalleeSecurityData& z,DceCalleeReport& report)
{
error_status_t s=0;
bool flag=false;
for(int i=0;i<option_count;++i)
{
if(options[i].protection_level != rpc_c_protect_level_none &&
options[i].protection_level != z.protection_level)
continue;
if(options[i].authentication_service != rpc_c_authn_none &&
options[i].authentication_service != z.authentication_service)
continue;
if(options[i].authorization_service != rpc_c_authz_none &&
options[i].authorization_service != z.authorization_service)
continue;
flag=true;
break;
}
if(option_count > 0 && !flag)
report.authorized=false;
if(report.authorized)
{
if(FALSE==sec_cred_is_authenticated(z.callers_identity,&s))
report.authorized=false;
if(s!=rpc_s_ok)
{
report.authorized=false;
dce_log("can't authenticate",s);
}
}
unsigned_char_t *client_principal_name=0;
sec_cred_get_client_princ_name(z.callers_identity,&client_principal_name,&s);
if(s!=rpc_s_ok )
{
sec_rgy_handle_t sec_context=0;
unsigned_char_t *client_site_name = 0; // local "/.:"
uuid_t *id=0;
sec_rgy_name_t pgo_name;
sec_cred_pa_handle_t pa_handle;
sec_id_pa_t *sec_id_handle;
pa_handle=sec_cred_get_initiator(
z.callers_identity,
&s);
if(s==rpc_s_ok )
{
sec_id_handle=sec_cred_get_pa_data(
pa_handle,
&s);
id=&(sec_id_handle->principal.uuid);
}
if(s==rpc_s_ok )
sec_rgy_site_open(
client_site_name,
&sec_context,
&s);
if(s==rpc_s_ok )
sec_rgy_pgo_id_to_name(
sec_context,
sec_rgy_domain_person,
id,
pgo_name,
&s);
if(s!=rpc_s_ok )
dce_log("can't get client principal name",s);
else
{
client_principal_name=(unsigned_char_t*)pgo_name;
if( report.set_name(client_principal_name) )
report.authorized=false;
}
sec_rgy_site_close(
sec_context,
&s);
}
else
{
if( report.set_name(client_principal_name) )
report.authorized=false;
}
if(report.authorized)
report.authorized=check_client_principal_name((char*)client_principal_name);
if(server_principal_name && z.server_principal_name && report.authorized)
{
if( strcmp((char*) server_principal_name, (char*)z.server_principal_name) )
report.authorized=false;
}
}
void DceCallee::start_dce_response(handle_t h,DceCalleeReport& report,error_status_t *s)
{
DceCalleeSecurityData z;
rpc_binding_inq_auth_caller(
h,
&z.callers_identity,
&z.server_principal_name,
&z.protection_level,
&z.authentication_service,
&z.authorization_service,
s);
if(*s!=rpc_s_ok)
dce_log("can't get caller data",*s);
if(*s==rpc_s_ok && level1_check)
check_level1(z,report);
if(*s==rpc_s_ok && level1_check && level2_check && report.authorized)
check_level2(h,z,report,s);
}
int DceCallee::dce_log(const char *message, error_status_t ss)
{
dce_error_string_t error_text;
int s=0;
#ifdef OUT
dce_error_inq_text(ss,error_text,&s);
if(!s)
fprintf(OUT,"%s; dce call error: %s\n",message,(char*)error_text);
else
fprintf(OUT,"%s; dce call error: %d\n",message,(int)ss);
#endif
return 0;
}