acct_util.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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 "acctpolicy.h"
  22. #include "slapi-plugin.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. {
  75. Slapi_DN *sdn = NULL;
  76. Slapi_Entry *policy_entry = NULL;
  77. Slapi_Attr *attr;
  78. Slapi_Value *sval = NULL;
  79. int ldrc;
  80. char *attr_name;
  81. char *policy_dn = NULL;
  82. acctPluginCfg *cfg;
  83. int rc = 0;
  84. if( policy == NULL ) {
  85. /* Bad parameter */
  86. return( -1 );
  87. }
  88. *policy = NULL;
  89. config_rd_lock();
  90. cfg = get_config();
  91. /* Return success and NULL policy */
  92. policy_dn = get_attr_string_val( target_entry, cfg->spec_attr_name );
  93. if( policy_dn == NULL ) {
  94. slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
  95. "get_acctpolicy - \"%s\" is not governed by an account inactivity "
  96. "policy subentry\n", slapi_entry_get_ndn( target_entry ) );
  97. if (cfg->inactivitylimit != ULONG_MAX) {
  98. goto dopolicy;
  99. }
  100. slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
  101. "get_acctpolicy - \"%s\" is not governed by an account inactivity "
  102. "global policy\n", slapi_entry_get_ndn( target_entry ) );
  103. config_unlock();
  104. return rc;
  105. }
  106. sdn = slapi_sdn_new_dn_byref( policy_dn );
  107. ldrc = slapi_search_internal_get_entry( sdn, NULL, &policy_entry,
  108. plugin_id );
  109. slapi_sdn_free( &sdn );
  110. /* There should be a policy but it can't be retrieved; fatal error */
  111. if( policy_entry == NULL ) {
  112. if( ldrc != LDAP_NO_SUCH_OBJECT ) {
  113. slapi_log_err(SLAPI_LOG_ERR, PLUGIN_NAME,
  114. "get_acctpolicy - Error retrieving policy entry \"%s\": %d\n", policy_dn, ldrc );
  115. } else {
  116. slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
  117. "get_acctpolicy - Policy entry \"%s\" is missing: %d\n", policy_dn, ldrc );
  118. }
  119. rc = -1;
  120. goto done;
  121. }
  122. dopolicy:
  123. *policy = (acctPolicy *)slapi_ch_calloc( 1, sizeof( acctPolicy ) );
  124. if ( !policy_entry ) { /* global policy */
  125. (*policy)->inactivitylimit = cfg->inactivitylimit;
  126. goto done;
  127. }
  128. for( slapi_entry_first_attr( policy_entry, &attr ); attr != NULL;
  129. slapi_entry_next_attr( policy_entry, attr, &attr ) ) {
  130. slapi_attr_get_type(attr, &attr_name);
  131. if( !strcasecmp( attr_name, cfg->limit_attr_name ) ) {
  132. if( slapi_attr_first_value( attr, &sval ) == 0 ) {
  133. (*policy)->inactivitylimit = slapi_value_get_ulong( sval );
  134. }
  135. }
  136. }
  137. done:
  138. config_unlock();
  139. slapi_ch_free_string( &policy_dn );
  140. slapi_entry_free( policy_entry );
  141. return( rc );
  142. }
  143. /*
  144. Frees an account policy allocated by get_acctpolicy()
  145. */
  146. void
  147. free_acctpolicy( acctPolicy **policy ) {
  148. slapi_ch_free( (void**)policy );
  149. return;
  150. }
  151. /*
  152. Plugin plumbing
  153. */
  154. void
  155. set_identity(void *identity) {
  156. plugin_id = identity;
  157. }
  158. /*
  159. Plugin plumbing
  160. */
  161. void*
  162. get_identity() {
  163. return( plugin_id );
  164. }
  165. /*
  166. A more flexible atoi(), converts to integer and returns the characters
  167. between (src+offset) and (src+offset+len). No support for negative numbers,
  168. which doesn't affect our time parsing.
  169. */
  170. int
  171. antoi( char *src, int offset, int len ) {
  172. int pow = 1, res = 0;
  173. if( len < 0 ) {
  174. return( -1 );
  175. }
  176. while( --len != -1 ) {
  177. if( !isdigit( src[offset+len] ) ) {
  178. res = -1;
  179. break;
  180. } else {
  181. res += ( src[offset+len] - '0' ) * pow ;
  182. pow *= 10;
  183. }
  184. }
  185. return( res );
  186. }
  187. /*
  188. Converts generalized time to UNIX GMT time. For example:
  189. "20060807211257Z" -> 1154981577
  190. */
  191. time_t
  192. gentimeToEpochtime( char *gentimestr ) {
  193. time_t epochtime, cur_local_epochtime, cur_gm_epochtime, zone_offset;
  194. struct tm t, *cur_gm_time;
  195. /* Find the local offset from GMT */
  196. cur_gm_time = (struct tm*)slapi_ch_calloc( 1, sizeof( struct tm ) );
  197. cur_local_epochtime = time( (time_t *)0 );
  198. gmtime_r( &cur_local_epochtime, cur_gm_time );
  199. cur_gm_epochtime = mktime( cur_gm_time );
  200. free( cur_gm_time );
  201. zone_offset = cur_gm_epochtime - cur_local_epochtime;
  202. /* Parse generalizedtime string into a tm struct */
  203. t.tm_year = antoi( gentimestr, 0, 4 ) - 1900;
  204. t.tm_mon = antoi( gentimestr, 4, 2 ) - 1;
  205. t.tm_mday = antoi( gentimestr, 6, 2 );
  206. t.tm_hour = antoi( gentimestr, 8, 2 );
  207. t.tm_min = antoi( gentimestr, 10, 2 );
  208. t.tm_sec = antoi( gentimestr, 12, 2 );
  209. t.tm_isdst = 0; /* DST does not apply to UTC */
  210. /* Turn tm object into local epoch time */
  211. epochtime = mktime( &t );
  212. /* Turn local epoch time into GMT epoch time */
  213. epochtime -= zone_offset;
  214. return( epochtime );
  215. }
  216. /*
  217. Converts UNIX time to generalized time. For example:
  218. 1154981577 -> "20060807211257Z"
  219. */
  220. char*
  221. epochtimeToGentime( time_t epochtime ) {
  222. char *gentimestr;
  223. struct tm t;
  224. gmtime_r( &epochtime, &t );
  225. gentimestr = slapi_ch_malloc( 20 );
  226. /* Format is YYYYmmddHHMMSSZ (15+1 chars) */
  227. strftime( gentimestr, 16, "%Y%m%d%H%M%SZ", &t );
  228. return( gentimestr );
  229. }
  230. int update_is_allowed_attr (const char *attr)
  231. {
  232. int i;
  233. /* check list of attributes that cannot be used for login recording */
  234. for (i = 0; protected_attrs_login_recording[i]; i ++) {
  235. if (strcasecmp (attr, protected_attrs_login_recording[i]) == 0) {
  236. /* this attribute is not allowed */
  237. return 0;
  238. }
  239. }
  240. return 1;
  241. }