/****************************************************************************** Copyright (C) 2009 Hewlett-Packard Development Company, L.P. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Contributors: Hewlett-Packard Development Company, L.P. ******************************************************************************/ #include #include #include #include #include #include "slapi-plugin.h" #include "acctpolicy.h" /* Globals */ static void* plugin_id = NULL; /* Checks whether an entry has a particular attribute type, and optionally returns the value. Only for use with single-valued attributes - it returns the first value it finds. */ int has_attr( Slapi_Entry* target_entry, char* attr_name, char** val ) { Slapi_ValueSet *values = NULL; Slapi_Value* sval; char *actual_type_name = NULL; int type_name_disposition = 0, attr_free_flags = 0, rc = 0; /* Use vattr interface to support virtual attributes, e.g. acctPolicySubentry has a good chance of being supplied by CoS */ if ( slapi_vattr_values_get( target_entry, attr_name, &values, &type_name_disposition, &actual_type_name, 0, &attr_free_flags) == 0) { if( slapi_valueset_first_value( values, &sval ) == -1 ) { rc = 0; } else { rc = 1; if( val ) { /* Caller wants a copy of the found attribute's value */ *val = slapi_ch_strdup( slapi_value_get_string( sval ) ); } } } else { rc = 0; } slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags); return( rc ); } /* Lazy wrapper for has_attr() */ char* get_attr_string_val( Slapi_Entry* target_entry, char* attr_name ) { char* ret = NULL; has_attr( target_entry, attr_name, &ret ); return( ret ); } /* Given an entry, provide the account policy in effect for that entry. Returns non-0 if function fails. If account policy comes back NULL, it's not an error; the entry is simply not covered by a policy. */ int get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry, void *plugin_id, acctPolicy **policy ) { Slapi_DN *sdn = NULL; Slapi_Entry *policy_entry = NULL; Slapi_Attr *attr; Slapi_Value *sval = NULL; int ldrc; char *attr_name; char *policy_dn = NULL; acctPluginCfg *cfg; int rc = 0; cfg = get_config(); if( policy == NULL ) { /* Bad parameter */ return( -1 ); } *policy = NULL; /* Return success and NULL policy */ policy_dn = get_attr_string_val( target_entry, cfg->spec_attr_name ); if( policy_dn == NULL ) { slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME, "\"%s\" is not governed by an account inactivity " "policy subentry\n", slapi_entry_get_ndn( target_entry ) ); if (cfg->inactivitylimit != ULONG_MAX) { goto dopolicy; } slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME, "\"%s\" is not governed by an account inactivity " "global policy\n", slapi_entry_get_ndn( target_entry ) ); return rc; } sdn = slapi_sdn_new_dn_byref( policy_dn ); ldrc = slapi_search_internal_get_entry( sdn, NULL, &policy_entry, plugin_id ); slapi_sdn_free( &sdn ); /* There should be a policy but it can't be retrieved; fatal error */ if( policy_entry == NULL ) { if( ldrc != LDAP_NO_SUCH_OBJECT ) { slapi_log_error( SLAPI_LOG_FATAL, PLUGIN_NAME, "Error retrieving policy entry \"%s\": %d\n", policy_dn, ldrc ); } else { slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME, "Policy entry \"%s\" is missing: %d\n", policy_dn, ldrc ); } rc = -1; goto done; } dopolicy: *policy = (acctPolicy *)slapi_ch_calloc( 1, sizeof( acctPolicy ) ); if ( !policy_entry ) { /* global policy */ (*policy)->inactivitylimit = cfg->inactivitylimit; goto done; } for( slapi_entry_first_attr( policy_entry, &attr ); attr != NULL; slapi_entry_next_attr( policy_entry, attr, &attr ) ) { slapi_attr_get_type(attr, &attr_name); if( !strcasecmp( attr_name, cfg->limit_attr_name ) ) { if( slapi_attr_first_value( attr, &sval ) == 0 ) { (*policy)->inactivitylimit = slapi_value_get_ulong( sval ); } } } done: slapi_ch_free_string( &policy_dn ); slapi_entry_free( policy_entry ); return( rc ); } /* Frees an account policy allocated by get_acctpolicy() */ void free_acctpolicy( acctPolicy **policy ) { slapi_ch_free( (void**)policy ); return; } /* Plugin plumbing */ void set_identity(void *identity) { plugin_id = identity; } /* Plugin plumbing */ void* get_identity() { return( plugin_id ); } /* A more flexible atoi(), converts to integer and returns the characters between (src+offset) and (src+offset+len). No support for negative numbers, which doesn't affect our time parsing. */ int antoi( char *src, int offset, int len ) { int pow = 1, res = 0; if( len < 0 ) { return( -1 ); } while( --len != -1 ) { if( !isdigit( src[offset+len] ) ) { res = -1; break; } else { res += ( src[offset+len] - '0' ) * pow ; pow *= 10; } } return( res ); } /* Converts generalized time to UNIX GMT time. For example: "20060807211257Z" -> 1154981577 */ time_t gentimeToEpochtime( char *gentimestr ) { time_t epochtime, cur_local_epochtime, cur_gm_epochtime, zone_offset; struct tm t, *cur_gm_time; /* Find the local offset from GMT */ cur_gm_time = (struct tm*)slapi_ch_calloc( 1, sizeof( struct tm ) ); cur_local_epochtime = time( (time_t)0 ); gmtime_r( &cur_local_epochtime, cur_gm_time ); cur_gm_epochtime = mktime( cur_gm_time ); free( cur_gm_time ); zone_offset = cur_gm_epochtime - cur_local_epochtime; /* Parse generalizedtime string into a tm struct */ t.tm_year = antoi( gentimestr, 0, 4 ) - 1900; t.tm_mon = antoi( gentimestr, 4, 2 ) - 1; t.tm_mday = antoi( gentimestr, 6, 2 ); t.tm_hour = antoi( gentimestr, 8, 2 ); t.tm_min = antoi( gentimestr, 10, 2 ); t.tm_sec = antoi( gentimestr, 12, 2 ); t.tm_isdst = 0; /* DST does not apply to UTC */ /* Turn tm object into local epoch time */ epochtime = mktime( &t ); /* Turn local epoch time into GMT epoch time */ epochtime -= zone_offset; return( epochtime ); } /* Converts UNIX time to generalized time. For example: 1154981577 -> "20060807211257Z" */ char* epochtimeToGentime( time_t epochtime ) { char *gentimestr; struct tm t; gmtime_r( &epochtime, &t ); gentimestr = slapi_ch_malloc( 20 ); /* Format is YYYYmmddHHMMSSZ (15+1 chars) */ strftime( gentimestr, 16, "%Y%m%d%H%M%SZ", &t ); return( gentimestr ); }