acct_util.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /******************************************************************************
  2. Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. version 2 as published by the Free Software Foundation.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; if not, write to the Free Software
  12. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  13. Contributors:
  14. Hewlett-Packard Development Company, L.P.
  15. ******************************************************************************/
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <time.h>
  20. #include <ctype.h>
  21. #include "slapi-plugin.h"
  22. #include "acctpolicy.h"
  23. /* Globals */
  24. static void* plugin_id = NULL;
  25. /* attributes that no clients are allowed to add or modify */
  26. static char *protected_attrs_login_recording [] = { "createTimestamp",
  27. NULL };
  28. /*
  29. Checks whether an entry has a particular attribute type, and optionally
  30. returns the value. Only for use with single-valued attributes - it returns
  31. the first value it finds.
  32. */
  33. int
  34. has_attr( Slapi_Entry* target_entry, char* attr_name, char** val ) {
  35. Slapi_ValueSet *values = NULL;
  36. Slapi_Value* sval;
  37. char *actual_type_name = NULL;
  38. int type_name_disposition = 0, attr_free_flags = 0, rc = 0;
  39. /* Use vattr interface to support virtual attributes, e.g.
  40. acctPolicySubentry has a good chance of being supplied by CoS */
  41. if ( slapi_vattr_values_get( target_entry, attr_name, &values, &type_name_disposition, &actual_type_name, 0, &attr_free_flags) == 0) {
  42. if( slapi_valueset_first_value( values, &sval ) == -1 ) {
  43. rc = 0;
  44. } else {
  45. rc = 1;
  46. if( val ) {
  47. /* Caller wants a copy of the found attribute's value */
  48. *val = slapi_ch_strdup( slapi_value_get_string( sval ) );
  49. }
  50. }
  51. } else {
  52. rc = 0;
  53. }
  54. slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
  55. return( rc );
  56. }
  57. /*
  58. Lazy wrapper for has_attr()
  59. */
  60. char*
  61. get_attr_string_val( Slapi_Entry* target_entry, char* attr_name ) {
  62. char* ret = NULL;
  63. has_attr( target_entry, attr_name, &ret );
  64. return( ret );
  65. }
  66. /*
  67. Given an entry, provide the account policy in effect for that entry.
  68. Returns non-0 if function fails. If account policy comes back NULL, it's
  69. not an error; the entry is simply not covered by a policy.
  70. */
  71. int
  72. get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry, void *plugin_id,
  73. acctPolicy **policy ) {
  74. Slapi_DN *sdn = NULL;
  75. Slapi_Entry *policy_entry = NULL;
  76. Slapi_Attr *attr;
  77. Slapi_Value *sval = NULL;
  78. int ldrc;
  79. char *attr_name;
  80. char *policy_dn = NULL;
  81. acctPluginCfg *cfg;
  82. int rc = 0;
  83. cfg = get_config();
  84. if( policy == NULL ) {
  85. /* Bad parameter */
  86. return( -1 );
  87. }
  88. *policy = NULL;
  89. /* Return success and NULL policy */
  90. policy_dn = get_attr_string_val( target_entry, cfg->spec_attr_name );
  91. if( policy_dn == NULL ) {
  92. slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
  93. "\"%s\" is not governed by an account inactivity "
  94. "policy subentry\n", slapi_entry_get_ndn( target_entry ) );
  95. if (cfg->inactivitylimit != ULONG_MAX) {
  96. goto dopolicy;
  97. }
  98. slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
  99. "\"%s\" is not governed by an account inactivity "
  100. "global policy\n", slapi_entry_get_ndn( target_entry ) );
  101. return rc;
  102. }
  103. sdn = slapi_sdn_new_dn_byref( policy_dn );
  104. ldrc = slapi_search_internal_get_entry( sdn, NULL, &policy_entry,
  105. plugin_id );
  106. slapi_sdn_free( &sdn );
  107. /* There should be a policy but it can't be retrieved; fatal error */
  108. if( policy_entry == NULL ) {
  109. if( ldrc != LDAP_NO_SUCH_OBJECT ) {
  110. slapi_log_error( SLAPI_LOG_FATAL, PLUGIN_NAME,
  111. "Error retrieving policy entry \"%s\": %d\n", policy_dn, ldrc );
  112. } else {
  113. slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
  114. "Policy entry \"%s\" is missing: %d\n", policy_dn, ldrc );
  115. }
  116. rc = -1;
  117. goto done;
  118. }
  119. dopolicy:
  120. *policy = (acctPolicy *)slapi_ch_calloc( 1, sizeof( acctPolicy ) );
  121. if ( !policy_entry ) { /* global policy */
  122. (*policy)->inactivitylimit = cfg->inactivitylimit;
  123. goto done;
  124. }
  125. for( slapi_entry_first_attr( policy_entry, &attr ); attr != NULL;
  126. slapi_entry_next_attr( policy_entry, attr, &attr ) ) {
  127. slapi_attr_get_type(attr, &attr_name);
  128. if( !strcasecmp( attr_name, cfg->limit_attr_name ) ) {
  129. if( slapi_attr_first_value( attr, &sval ) == 0 ) {
  130. (*policy)->inactivitylimit = slapi_value_get_ulong( sval );
  131. }
  132. }
  133. }
  134. done:
  135. slapi_ch_free_string( &policy_dn );
  136. slapi_entry_free( policy_entry );
  137. return( rc );
  138. }
  139. /*
  140. Frees an account policy allocated by get_acctpolicy()
  141. */
  142. void
  143. free_acctpolicy( acctPolicy **policy ) {
  144. slapi_ch_free( (void**)policy );
  145. return;
  146. }
  147. /*
  148. Plugin plumbing
  149. */
  150. void
  151. set_identity(void *identity) {
  152. plugin_id = identity;
  153. }
  154. /*
  155. Plugin plumbing
  156. */
  157. void*
  158. get_identity() {
  159. return( plugin_id );
  160. }
  161. /*
  162. A more flexible atoi(), converts to integer and returns the characters
  163. between (src+offset) and (src+offset+len). No support for negative numbers,
  164. which doesn't affect our time parsing.
  165. */
  166. int
  167. antoi( char *src, int offset, int len ) {
  168. int pow = 1, res = 0;
  169. if( len < 0 ) {
  170. return( -1 );
  171. }
  172. while( --len != -1 ) {
  173. if( !isdigit( src[offset+len] ) ) {
  174. res = -1;
  175. break;
  176. } else {
  177. res += ( src[offset+len] - '0' ) * pow ;
  178. pow *= 10;
  179. }
  180. }
  181. return( res );
  182. }
  183. /*
  184. Converts generalized time to UNIX GMT time. For example:
  185. "20060807211257Z" -> 1154981577
  186. */
  187. time_t
  188. gentimeToEpochtime( char *gentimestr ) {
  189. time_t epochtime, cur_local_epochtime, cur_gm_epochtime, zone_offset;
  190. struct tm t, *cur_gm_time;
  191. /* Find the local offset from GMT */
  192. cur_gm_time = (struct tm*)slapi_ch_calloc( 1, sizeof( struct tm ) );
  193. cur_local_epochtime = time( (time_t)0 );
  194. gmtime_r( &cur_local_epochtime, cur_gm_time );
  195. cur_gm_epochtime = mktime( cur_gm_time );
  196. free( cur_gm_time );
  197. zone_offset = cur_gm_epochtime - cur_local_epochtime;
  198. /* Parse generalizedtime string into a tm struct */
  199. t.tm_year = antoi( gentimestr, 0, 4 ) - 1900;
  200. t.tm_mon = antoi( gentimestr, 4, 2 ) - 1;
  201. t.tm_mday = antoi( gentimestr, 6, 2 );
  202. t.tm_hour = antoi( gentimestr, 8, 2 );
  203. t.tm_min = antoi( gentimestr, 10, 2 );
  204. t.tm_sec = antoi( gentimestr, 12, 2 );
  205. t.tm_isdst = 0; /* DST does not apply to UTC */
  206. /* Turn tm object into local epoch time */
  207. epochtime = mktime( &t );
  208. /* Turn local epoch time into GMT epoch time */
  209. epochtime -= zone_offset;
  210. return( epochtime );
  211. }
  212. /*
  213. Converts UNIX time to generalized time. For example:
  214. 1154981577 -> "20060807211257Z"
  215. */
  216. char*
  217. epochtimeToGentime( time_t epochtime ) {
  218. char *gentimestr;
  219. struct tm t;
  220. gmtime_r( &epochtime, &t );
  221. gentimestr = slapi_ch_malloc( 20 );
  222. /* Format is YYYYmmddHHMMSSZ (15+1 chars) */
  223. strftime( gentimestr, 16, "%Y%m%d%H%M%SZ", &t );
  224. return( gentimestr );
  225. }
  226. int update_is_allowed_attr (const char *attr)
  227. {
  228. int i;
  229. /* check list of attributes that cannot be used for login recording */
  230. for (i = 0; protected_attrs_login_recording[i]; i ++) {
  231. if (strcasecmp (attr, protected_attrs_login_recording[i]) == 0) {
  232. /* this attribute is not allowed */
  233. return 0;
  234. }
  235. }
  236. return 1;
  237. }