schemaparse.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /* schemaparse.c - routines to support objectclass definitions */
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <sys/types.h>
  42. #include "slap.h"
  43. /* global_oc and global_schema_csn are both protected by oc locks */
  44. struct objclass *global_oc;
  45. CSN *global_schema_csn = NULL; /* Timestamp for last update CSN. NULL = epoch */
  46. static int is_duplicate( char *target, char **list, int list_max );
  47. static void normalize_list( char **list );
  48. /* R/W lock used to protect the global objclass linked list. */
  49. static PRRWLock *oc_lock = NULL;
  50. /*
  51. * The oc_init_lock_callonce structure is used by NSPR to ensure
  52. * that oc_init_lock() is called at most once.
  53. */
  54. static PRCallOnceType oc_init_lock_callonce = { 0, 0, 0 };
  55. /* Create the objectclass read/write lock. Returns PRSuccess if successful */
  56. static PRStatus
  57. oc_init_lock( void )
  58. {
  59. if ( NULL == ( oc_lock = PR_NewRWLock( PR_RWLOCK_RANK_NONE,
  60. "objectclass rwlock" ))) {
  61. slapi_log_error( SLAPI_LOG_FATAL, "oc_init_lock",
  62. "PR_NewRWLock() for objectclass lock failed\n" );
  63. return PR_FAILURE;
  64. }
  65. return PR_SUCCESS;
  66. }
  67. void
  68. oc_lock_read( void )
  69. {
  70. if ( NULL != oc_lock ||
  71. PR_SUCCESS == PR_CallOnce( &oc_init_lock_callonce, oc_init_lock )) {
  72. PR_RWLock_Rlock( oc_lock );
  73. }
  74. }
  75. void
  76. oc_lock_write( void )
  77. {
  78. if ( NULL != oc_lock ||
  79. PR_SUCCESS == PR_CallOnce( &oc_init_lock_callonce, oc_init_lock )) {
  80. PR_RWLock_Wlock( oc_lock );
  81. }
  82. }
  83. void
  84. oc_unlock( void )
  85. {
  86. if ( oc_lock != NULL ) {
  87. PR_RWLock_Unlock( oc_lock );
  88. }
  89. }
  90. /*
  91. * Note: callers of g_get_global_oc_nolock() must hold a read or write lock
  92. */
  93. struct objclass* g_get_global_oc_nolock()
  94. {
  95. return global_oc;
  96. }
  97. /*
  98. * Note: callers of g_set_global_oc_nolock() must hold a write lock
  99. */
  100. void
  101. g_set_global_oc_nolock( struct objclass *newglobaloc )
  102. {
  103. global_oc = newglobaloc;
  104. }
  105. /*
  106. * Note: callers of g_get_global_schema_csn() must hold a read lock
  107. */
  108. const CSN *
  109. g_get_global_schema_csn()
  110. {
  111. return global_schema_csn;
  112. }
  113. /*
  114. * Note: callers of g_set_global_schema_csn() must hold a write lock.
  115. * csn is consumed.
  116. */
  117. void
  118. g_set_global_schema_csn(CSN *csn)
  119. {
  120. CSN *tmp = NULL;
  121. if (NULL != global_schema_csn)
  122. {
  123. tmp = global_schema_csn;
  124. }
  125. global_schema_csn = csn;
  126. if (NULL != tmp)
  127. {
  128. csn_free(&tmp);
  129. }
  130. }
  131. /*
  132. * There are two kinds of objectclasses:
  133. * Standard Objectclasses and User Defined Objectclasses
  134. *
  135. * Standard Objectclasses are the objectclasses which come with the Directory Server.
  136. * These objectclasses are always expected to be there and shouldn't be accidentally
  137. * changed by the end user. We dont' allow these objectclasses to be deleted, and the
  138. * admin CGIs will not allow the end user to change their definitions. However, we
  139. * will allow these objectclasses to be redefined via ldap_modify, by doing an LDAP_MOD_ADD.
  140. * The new definition will override the previous definition. The updated objectclass
  141. * will be written out the 00user.ldif and the original definition will stay
  142. * whereever it was originally defined. At startup, slapd will use the last definition
  143. * read as the real definition of an objectclass.
  144. *
  145. * User Defined ObjectClasses are objectclasses which were added to the Directory Server
  146. * by the end user. These objectclasses are also kept in 99user.ldif. These objectclasses
  147. * can be deleted by the end user.
  148. *
  149. * Every objectclass contains an array of attributes called oc_orig_required,
  150. * which are the required attributes for that objectclass which were not inherited from
  151. * any other objectclass. Likewise, there's also an array called oc_orig_allowed which
  152. * contains the allowed attributes which were not inherited from any other objectclass.
  153. *
  154. * The arrays oc_required and oc_allowed contain all the required and allowed attributes for
  155. * that objectclass, including the ones inherited from its parent and also the ones in
  156. * oc_orig_required and oc_orig_allowed.
  157. *
  158. * When an oc is updated, we go through the global list of objectclasses and see if
  159. * any ocs inherited from it. If so, we delete its oc_required and oc_allowed arrays,
  160. * copy the oc_orig_required and oc_orig_allowed arrays to oc_required and oc_allowed,
  161. * and then merge the parent's oc_required and oc_allowed onto oc_required and oc_allowed.
  162. *
  163. *
  164. */
  165. static int
  166. is_duplicate( char *target, char **list, int list_size ) {
  167. int i;
  168. for ( i = 0; i < list_size; i++ ) {
  169. if ( !strcasecmp( target, list[i] ) ) {
  170. return 1;
  171. }
  172. }
  173. return 0;
  174. }
  175. /*
  176. * Make normalized copies of all non-duplicate values in a list; free all old
  177. * values. The list is not resized.
  178. */
  179. static void
  180. normalize_list( char **list ) {
  181. int i, j;
  182. for ( i = 0, j = 0; list != NULL && list[i] != NULL; i++ ) {
  183. char *norm = slapi_attr_syntax_normalize( list[i] );
  184. char *save = list[i];
  185. if ( !is_duplicate( norm, list, j ) ) {
  186. list[j++] = norm;
  187. } else {
  188. slapi_ch_free((void **)&norm );
  189. }
  190. slapi_ch_free((void**)&save );
  191. }
  192. for ( ; j < i; j++ ) {
  193. list[j] = NULL;
  194. }
  195. }
  196. /*
  197. * normalize types contained in object class definitions. do this
  198. * after the whole config file is read so there is no order dependency
  199. * on inclusion of attributes and object classes.
  200. */
  201. void
  202. normalize_oc( void )
  203. {
  204. struct objclass *oc;
  205. oc_lock_write();
  206. for ( oc = g_get_global_oc_nolock(); oc != NULL; oc = oc->oc_next ) {
  207. LDAPDebug (LDAP_DEBUG_PARSE,
  208. "normalize_oc: normalizing '%s'\n", oc->oc_name, 0, 0);
  209. /* required attributes */
  210. normalize_list( oc->oc_required );
  211. normalize_list( oc->oc_orig_required );
  212. /* optional attributes */
  213. normalize_list( oc->oc_allowed );
  214. normalize_list( oc->oc_orig_allowed );
  215. }
  216. oc_unlock();
  217. }
  218. /*
  219. * oc_update_inheritance_nolock:
  220. * If an objectclass is redefined, we need to make sure that any objectclasses
  221. * which inherit from the redefined objectclass have their required and allowed
  222. * attributes updated.
  223. *
  224. * Every objectclass contains an array of attributes called oc_orig_required,
  225. * which are the required attributes for that objectclass which were not inherited from
  226. * any other objectclass. Likewise, there's also an array called oc_orig_allowed which
  227. * contains the allowed attributes which were not inherited from any other objectclass.
  228. *
  229. * The arrays oc_required and oc_allowed contain all the required and allowed attributes for
  230. * that objectclass, including the ones inherited from its parent and also the ones in
  231. * oc_orig_required and oc_orig_allowed.
  232. *
  233. * When an oc is updated, we go through the global list of objectclasses and see if
  234. * any ocs inherited from it. If so, we delete its oc_requried and oc_allowed arrays,
  235. * copy the oc_orig_required and oc_orig_allowed arrays to oc_required and oc_allowed,
  236. * and then merge the parent's oc_required and oc_allowed onto oc_required and oc_allowed.
  237. */
  238. void
  239. oc_update_inheritance_nolock( struct objclass *psuperior_oc )
  240. {
  241. struct objclass *oc;
  242. for ( oc = g_get_global_oc_nolock(); oc != NULL; oc = oc->oc_next ) {
  243. if ( oc->oc_superior &&
  244. (strcasecmp( oc->oc_superior, psuperior_oc->oc_name ) == 0) ) {
  245. if (oc->oc_required ) {
  246. charray_free (oc->oc_required);
  247. }
  248. if (oc->oc_allowed) {
  249. charray_free (oc->oc_allowed);
  250. }
  251. oc->oc_required = charray_dup ( oc->oc_orig_required );
  252. oc->oc_allowed = charray_dup ( oc->oc_orig_allowed );
  253. charray_merge ( &(oc->oc_required), psuperior_oc->oc_required, 1 );
  254. charray_merge ( &(oc->oc_allowed), psuperior_oc->oc_allowed, 1 );
  255. oc_update_inheritance_nolock ( oc );
  256. }
  257. }
  258. }