/* azn_ent_timeadi.cpp */
/*
* This entitlements service is designed to be used with a TAM authorization rule as an
* entitlements service which can populate attribute decision information (ADI) with
* particular values.
*
* This service will populate the following adi based on a call to a localtime(), which
* determines the time on the timezone set on the system where the entitlements service
* is running:
*
* adi_year - this will be populated with the current year (e.g. 2007)
* adi_month - current month from 00 (January) to 11 (December)
* adi_day - day of the current month
* adi_hour - hour of the current day (00-23)
* adi_minute - minute of the current hour (00-59)
* adi_second - seconds of the current minute (00-59)
*
* It can be used with an authorization rule similar to:
!TRUE!
!TRUE!
!FALSE!
* To build the entitlements service:
Compile the azn_ent_timeadi.c using a modified version of the Makefile that comes with the entitlements service demo code in /opt/PolicyDirector/example/ent_svc_demo/cpp (just change the filename, output file and set the desired build platform).
This should build a file called libazn_ent_timeadi.so (depending on platform).
Put this file in /usr/lib.
* To configure WebSEAL to use the entitlements service:
Modify the webseald-.conf file to include:
[aznapi-configuration]
dynamic-adi-entitlement-services = timeadi
[aznapi-entitlement-services]
timeadi = azn_ent_timeadi
*/
#include
#include
#include
#ifdef _WIN32
#include
#endif
#include
#include
#include
#ifdef _WIN32
#undef AZN_DECLSPEC
#define AZN_DECLSPEC __declspec(dllexport)
#else
#undef AZN_DECLSPEC
#define AZN_DECLSPEC
#endif
// use this flag (and recompile) to enable all the debug printf's you see in this file.
static int timeadi_debug = 0;
#define CHECK_AZN_STATUS(st,str) \
if ( st != AZN_S_COMPLETE ) \
{ \
printf( "Call to %s failed: %d\n", str, st ); \
printf( "Major: %d Minor: %d\n", azn_error_major( st ), azn_error_minor( st ) ); \
azn_error_get_string( st, &errstr ); \
printf( "Str: %s\n", errstr ); \
abort(); \
}
static void display_creds( const azn_creds_h_t creds );
static void display_attrlist( const char * title, const azn_attrlist_h_t attrlist );
static void build_entitlements( const azn_attrlist_h_t app_context, azn_attrlist_h_t * entitlements );
static const char * ADI_YEAR = "adi_year";
static const char * ADI_MONTH = "adi_month";
static const char * ADI_DAY = "adi_day";
static const char * ADI_HOUR = "adi_hour";
static const char * ADI_MINUTE = "adi_minute";
static const char * ADI_SECOND = "adi_second";
static const char * ADI_ATTRLIST_ENTRY = "AZN_PERMINFO_RULES_ADI_REQUEST";
AZN_DECLSPEC
azn_status_t
AZN_CALLTYPE
azn_service_initialize(
int argc,
char **argv,
azn_attrlist_h_t svcInit,
azn_attrlist_h_t *svcInfo
)
{
if ( timeadi_debug )
{
printf( "timeadi_ent initialize complete\n" );
}
return AZN_S_COMPLETE;
}
AZN_DECLSPEC
azn_status_t
AZN_CALLTYPE
azn_entitlement_get_entitlements(
const azn_creds_h_t creds /* in */,
const azn_string_t entitlements_svc_id /* in */,
const azn_attrlist_h_t app_context /* in */,
azn_attrlist_h_t *entitlements /* out */
)
{
if ( creds == AZN_C_INVALID_HANDLE )
{
return AZN_S_INVALID_CREDS_HDL;
}
if ( entitlements_svc_id == AZN_C_INVALID_HANDLE )
{
return AZN_S_INVALID_ENTITLEMENTS_SVC;
}
if ( app_context == AZN_C_INVALID_HANDLE )
{
return AZN_S_INVALID_ATTRLIST_HDL;
}
if ( entitlements == AZN_C_INVALID_HANDLE )
{
return AZN_S_INVALID_ATTRLIST_HDL;
}
/*
* Display the input data
*/
if ( timeadi_debug )
{
display_creds( creds );
printf( "\n\nEntitlements service id: %s\n", entitlements_svc_id );
display_attrlist( "\n\nAPP_CONTEXT", app_context );
}
build_entitlements( app_context, entitlements );
if ( timeadi_debug )
{
display_attrlist( "\n\nRETURNING ENTITLEMENTS", *entitlements );
}
return AZN_S_COMPLETE;
}
AZN_DECLSPEC
azn_status_t
AZN_CALLTYPE
azn_service_shutdown(
int argc,
char **argv,
azn_attrlist_h_t svcInit,
azn_attrlist_h_t *svcInfo
)
{
if ( timeadi_debug )
{
printf( "timeadi_ent shutdown complete\n" );
}
return AZN_S_COMPLETE;
}
static void display_creds( const azn_creds_h_t creds )
{
azn_status_t st = AZN_S_COMPLETE;
unsigned int num_of_subjects = 0;
azn_attrlist_h_t creds_attrlist = AZN_C_INVALID_HANDLE;
if ((st = azn_creds_num_of_subjects(creds, &num_of_subjects)) != AZN_S_COMPLETE)
{
printf("Error getting number of creds in chain");
}
printf("Number of creds: %d\n", num_of_subjects);
if ((st = azn_creds_get_attrlist_for_subject(creds, 0, &creds_attrlist)) != AZN_S_COMPLETE)
{
printf("Error getting extended fields");
}
display_attrlist( "Credential attributes", creds_attrlist );
}
static void display_attrlist( const char * title, const azn_attrlist_h_t attrlist )
{
azn_string_t *attr_names = 0;
azn_string_t value = 0;
int i = 0, j = 0;
unsigned int num_values = 0;
azn_status_t st = AZN_S_COMPLETE;
azn_string_t errstr = 0;
if ((st = azn_attrlist_get_names(attrlist, &attr_names)) != AZN_S_COMPLETE)
{
printf("Couldn't get names of extended fields");
}
if (attr_names == NULL)
{
printf("No extended fields found");
}
/*
* Output the available information about the attribute list.
*/
printf( "%s\n", title );
i = 0;
while ( attr_names[i] != 0 )
{
printf("Name[%d]: %s\n", i, attr_names[i] );
st = azn_attrlist_name_get_num( attrlist, attr_names[i], &num_values );
CHECK_AZN_STATUS( st, "azn_attrlist_name_get_num" );
for ( j = 0; j < (int) num_values; j++ )
{
st = azn_attrlist_get_entry_string_value( attrlist, attr_names[i], j, &value );
CHECK_AZN_STATUS( st, "azn_attrlist_get_entry_string_value" );
printf( " Value[%d]: %s\n", j, value );
st = azn_release_string( &value );
CHECK_AZN_STATUS( st, "azn_release_string" );
}
i++;
}
st = azn_release_strings( &attr_names );
CHECK_AZN_STATUS( st, "azn_release_string" );
}
static unsigned int power_of(unsigned int num, unsigned int power)
{
unsigned int i = 0;
unsigned int result = 1;
for ( i = 0; i < power; i++ )
{
result = result * num;
}
return result;
}
static void write_number_to_string(char * str, unsigned short max_digits, unsigned int num)
{
int i = 0;
int j = 0;
for ( i = max_digits; i > 0; i-- )
{
str[j++] = '0' + ((num%power_of(10,i))/power_of(10,i-1));
}
str[j] = '\0';
}
static void build_entitlements( const azn_attrlist_h_t app_context, azn_attrlist_h_t * entitlements )
{
azn_status_t st = AZN_S_COMPLETE;
azn_string_t errstr = 0;
azn_string_t value = 0;
int i = 0;
unsigned int num_values = 0;
time_t mytime;
struct tm timeinfo;
char year[5];
char month[3];
char day[3];
char hour_of_day[3];
char minute_of_hour[3];
char second_of_minute[3];
year[0] = '\0';
month[0] = '\0';
day[0] = '\0';
hour_of_day[0] = '\0';
minute_of_hour[0] = '\0';
second_of_minute[0] = '\0';
/*
* Build the attrlist if necessary
*/
if ( *entitlements == AZN_C_INVALID_HANDLE )
{
st = azn_attrlist_create( entitlements );
CHECK_AZN_STATUS( st, "azn_attrlist_create" );
}
/*
* Get time elements ready
*/
if ( time( &mytime ) > 0 )
{
#ifdef _WIN32
if ( !localtime_s( &timeinfo, &mytime ) )
#else
if ( localtime_r( &mytime, &timeinfo ) != NULL )
#endif
{
if ( timeadi_debug )
{
printf("Time elements from localtime:\n" );
printf(" Year: %d\n", timeinfo.tm_year );
printf(" Month: %d\n", timeinfo.tm_mon );
printf(" Day: %d\n", timeinfo.tm_mday );
printf(" Hour: %d\n", timeinfo.tm_hour );
printf("Minute: %d\n", timeinfo.tm_min );
printf("Second: %d\n", timeinfo.tm_sec );
}
write_number_to_string(year, 4, 1900 + timeinfo.tm_year);
write_number_to_string(month, 2, timeinfo.tm_mon);
write_number_to_string(day, 2, timeinfo.tm_mday);
write_number_to_string(hour_of_day, 2, timeinfo.tm_hour);
write_number_to_string(minute_of_hour, 2, timeinfo.tm_min);
write_number_to_string(second_of_minute, 2, timeinfo.tm_sec);
}
else
{
if ( timeadi_debug )
{
#ifdef _WIN32
printf("Calling of localtime_s() function failed\n" );
#else
printf("Calling of localtime_r() function failed\n" );
#endif
}
}
}
else
{
if ( timeadi_debug )
{
printf("Calling of time() function failed\n" );
}
}
if ( timeadi_debug )
{
printf("Final time elements:\n" );
printf(" Year: %s\n", year );
printf(" Month: %s\n", month );
printf(" Day: %s\n", day );
printf(" Hour: %s\n", hour_of_day );
printf("Minute: %s\n", minute_of_hour );
printf("Second: %s\n", second_of_minute );
}
/*
* Now for each attribute in the app_context, add a value to the entitlements list with value NO_VALUE
*/
st = azn_attrlist_name_get_num( app_context, (char *) ADI_ATTRLIST_ENTRY, &num_values );
CHECK_AZN_STATUS( st, "azn_attrlist_name_get_num" );
for ( i = 0; i < (int) num_values; i++ )
{
st = azn_attrlist_get_entry_string_value( app_context, (char *) ADI_ATTRLIST_ENTRY, i, &value );
CHECK_AZN_STATUS( st, "azn_attrlist_get_entry_string_value" );
const char * vptr = 0;
if ( !strcmp( value, ADI_YEAR ) )
{
vptr = &year[0];
}
else if ( !strcmp( value, ADI_MONTH ) )
{
vptr = &month[0];
}
else if ( !strcmp( value, ADI_DAY ) )
{
vptr = &day[0];
}
else if ( !strcmp( value, ADI_HOUR ) )
{
vptr = &hour_of_day[0];
}
else if ( !strcmp( value, ADI_MINUTE ) )
{
vptr = &minute_of_hour[0];
}
else if ( !strcmp( value, ADI_SECOND ) )
{
vptr = &second_of_minute[0];
}
if ( vptr != 0 )
{
st = azn_attrlist_add_entry(
*entitlements,
value,
(char *) vptr );
CHECK_AZN_STATUS( st, "azn_attrlist_add_entry" );
}
st = azn_release_string( &value );
CHECK_AZN_STATUS( st, "azn_release_string" );
}
}