rootdse.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* rootdse.c - routines to manage the root DSE */
  13. #include <stdio.h>
  14. #include "slap.h"
  15. #include "fe.h"
  16. /* XXXmcs: why not look at the NO-USER-MODIFICATION flag instead? */
  17. static char *readonly_attributes[] = {
  18. "namingcontexts",
  19. "nsBackendSuffix",
  20. "subschemasubentry",
  21. "supportedldapversion",
  22. "supportedcontrol",
  23. "supportedextension",
  24. "supportedfeatures",
  25. "supportedsaslmechanisms",
  26. "dataversion",
  27. "ref",
  28. "vendorName",
  29. "vendorVersion",
  30. ATTR_NETSCAPEMDSUFFIX,
  31. NULL
  32. };
  33. static char *writable_attributes[] = {
  34. "copiedfrom",
  35. "copyingfrom",
  36. "aci",
  37. NULL
  38. };
  39. /*
  40. * function: is_readonly_attr
  41. * args: attr - candidate attribute name
  42. * returns: 0 if this attribute may be written to the root DSE
  43. * 1 if it may not be written.
  44. * notes: should probably be integrated into syntax AVL tree, so that
  45. * this list can be configured at runtime.
  46. */
  47. static int
  48. rootdse_is_readonly_attr( char *attr )
  49. {
  50. int i;
  51. if ( NULL == attr ) {
  52. return 1; /* I guess. It's not really an attribute at all */
  53. }
  54. /*
  55. * optimization: check for attributes we're likely to be writing
  56. * frequently.
  57. */
  58. for ( i = 0; NULL != writable_attributes[ i ]; i++ ) {
  59. if ( strncasecmp( attr, writable_attributes[ i ],
  60. strlen( writable_attributes[ i ])) == 0 ) {
  61. return 0;
  62. }
  63. }
  64. for ( i = 0; NULL != readonly_attributes[ i ]; i++ ) {
  65. if ( strncasecmp( attr, readonly_attributes[ i ],
  66. strlen( readonly_attributes[ i ])) == 0 ) {
  67. return 1;
  68. }
  69. }
  70. return 0;
  71. }
  72. /*
  73. * Handle a read operation on the root DSE (the entry with DN "");
  74. * Note: we're copying a lot of attributes here. It might be better
  75. * to keep track of which we really need to free, and arrange that
  76. * the others are unlinked from the attribute list of the entry
  77. * before calling slapi_entry_free().
  78. */
  79. int
  80. read_root_dse( Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg )
  81. {
  82. int i;
  83. struct berval *vals[2];
  84. struct berval val;
  85. struct berval **bvals;
  86. Slapi_Backend *be;
  87. char *cookie = NULL;
  88. char **strs;
  89. void *node;
  90. Slapi_DN *sdn;
  91. /*
  92. * Check that we were doing a base search on the root dse.
  93. */
  94. {
  95. int scope;
  96. slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
  97. if(scope!=LDAP_SCOPE_BASE)
  98. {
  99. *returncode= LDAP_NO_SUCH_OBJECT;
  100. return SLAPI_DSE_CALLBACK_ERROR;
  101. }
  102. }
  103. vals[0] = &val;
  104. vals[1] = NULL;
  105. /* loop through backend suffixes to get namingcontexts attr */
  106. attrlist_delete( &e->e_attrs, "namingcontexts");
  107. sdn = slapi_get_first_suffix(&node, 0);
  108. while (sdn)
  109. {
  110. val.bv_val = (char*)slapi_sdn_get_dn(sdn); /* jcm: had to cast away const */
  111. val.bv_len = strlen( val.bv_val );
  112. attrlist_merge( &e->e_attrs, "namingcontexts", vals );
  113. sdn = slapi_get_next_suffix(&node, 0);
  114. }
  115. val.bv_val = config_get_default_naming_context();
  116. if (val.bv_val) {
  117. val.bv_len = strlen(val.bv_val);
  118. attrlist_replace( &e->e_attrs, "defaultnamingcontext", vals );
  119. }
  120. attrlist_delete( &e->e_attrs, "nsBackendSuffix");
  121. for (be = slapi_get_first_backend(&cookie); be != NULL;
  122. be = slapi_get_next_backend(cookie)) {
  123. char * base;
  124. char * be_name;
  125. const Slapi_DN *be_suffix;
  126. if (slapi_be_private(be)) continue;
  127. /* tolerate a backend under construction containing no suffix */
  128. if ((be_suffix = slapi_be_getsuffix(be, 0)) == NULL) continue;
  129. if ((base = (char *)slapi_sdn_get_dn(be_suffix)) == NULL) continue;
  130. if ((be_name = slapi_be_get_name(be)) == NULL) continue;
  131. val.bv_len = strlen(base)+strlen(be_name)+1;
  132. val.bv_val = slapi_ch_malloc(val.bv_len+1);
  133. sprintf(val.bv_val, "%s:%s", be_name, base);
  134. attrlist_merge(&e->e_attrs, "nsBackendSuffix", vals);
  135. slapi_ch_free((void **) &val.bv_val);
  136. }
  137. slapi_ch_free((void **)&cookie);
  138. /* schema entry */
  139. val.bv_val = SLAPD_SCHEMA_DN;
  140. val.bv_len = sizeof( SLAPD_SCHEMA_DN ) - 1;
  141. attrlist_replace( &e->e_attrs, "subschemasubentry", vals );
  142. /* supported extended operations */
  143. attrlist_delete( &e->e_attrs, "supportedExtension");
  144. if (( strs = slapi_get_supported_extended_ops_copy()) != NULL ) {
  145. for ( i = 0; strs[i] != NULL; ++i ) {
  146. val.bv_val = strs[i];
  147. val.bv_len = strlen( strs[i] );
  148. attrlist_merge( &e->e_attrs, "supportedExtension", vals );
  149. }
  150. charray_free(strs);
  151. }
  152. /* supported controls */
  153. attrlist_delete( &e->e_attrs, "supportedControl");
  154. if ( slapi_get_supported_controls_copy( &strs, NULL ) == 0
  155. && strs != NULL ) {
  156. for ( i = 0; strs[i] != NULL; ++i ) {
  157. val.bv_val = strs[i];
  158. val.bv_len = strlen( strs[i] );
  159. attrlist_merge( &e->e_attrs, "supportedControl", vals );
  160. }
  161. charray_free(strs);
  162. }
  163. /* supported features */
  164. attrlist_delete( &e->e_attrs, "supportedFeatures");
  165. if ( slapi_get_supported_features_copy( &strs ) == 0
  166. && strs != NULL ) {
  167. for ( i = 0; strs[i] != NULL; ++i ) {
  168. val.bv_val = strs[i];
  169. val.bv_len = strlen( strs[i] );
  170. attrlist_merge( &e->e_attrs, "supportedFeatures", vals );
  171. }
  172. charray_free(strs);
  173. }
  174. /* supported sasl mechanisms */
  175. attrlist_delete( &e->e_attrs, "supportedSASLMechanisms");
  176. if (( strs = ids_sasl_listmech (pb)) != NULL ) {
  177. for ( i = 0; strs[i] != NULL; ++i ) {
  178. val.bv_val = strs[i];
  179. val.bv_len = strlen( strs[i] );
  180. attrlist_merge( &e->e_attrs, "supportedSASLMechanisms", vals );
  181. }
  182. charray_free(strs);
  183. }
  184. /* supported LDAP versions */
  185. val.bv_val = "2";
  186. val.bv_len = 1;
  187. attrlist_replace( &e->e_attrs, "supportedldapversion", vals );
  188. val.bv_val = "3";
  189. val.bv_len = 1;
  190. attrlist_merge( &e->e_attrs, "supportedldapversion", vals );
  191. /* superior references (ref attribute) */
  192. attrlist_delete( &e->e_attrs, "ref");
  193. if (( bvals = g_get_default_referral()) != NULL ) {
  194. for ( i = 0; bvals[i] != NULL; ++i ) {
  195. val.bv_val = bvals[i]->bv_val;
  196. val.bv_len = bvals[i]->bv_len;
  197. attrlist_merge( &e->e_attrs, "ref", vals );
  198. }
  199. }
  200. /* RFC 3045 attributes: vendorName and vendorVersion */
  201. val.bv_val = SLAPD_VENDOR_NAME;
  202. val.bv_len = strlen( val.bv_val );
  203. attrlist_replace( &e->e_attrs, "vendorName", vals );
  204. val.bv_val = slapd_get_version_value();
  205. val.bv_len = strlen( val.bv_val );
  206. attrlist_replace( &e->e_attrs, "vendorVersion", vals );
  207. slapi_ch_free( (void **)&val.bv_val );
  208. /* Server Data Version */
  209. if (( val.bv_val = (char*)get_server_dataversion()) != NULL ) { /* jcm cast away const */
  210. val.bv_len = strlen( val.bv_val );
  211. attrlist_replace( &e->e_attrs, attr_dataversion, vals );
  212. }
  213. /* machine data suffix
  214. * this has been added in 4.0 for replication purpose
  215. * and since 5.0 is now unused by the core server,
  216. * however some functionalities of the console framework 5.01
  217. * still depend on this
  218. */
  219. if (( val.bv_val = get_config_DN()) != NULL ) {
  220. val.bv_len = strlen( val.bv_val );
  221. attrlist_replace( &e->e_attrs, ATTR_NETSCAPEMDSUFFIX, vals );
  222. }
  223. #ifdef notdef
  224. /* XXXggood testing - print the size of the changelog db */
  225. {
  226. unsigned int clsize;
  227. clsize = get_changelog_size();
  228. sprintf( buf, "%u", clsize );
  229. val.bv_val = buf;
  230. val.bv_len = strlen( buf );
  231. attrlist_replace( &e->e_attrs, "changelogsize", vals );
  232. slapi_ch_free((void**)&val.bv_val );
  233. }
  234. #endif /* notdef */
  235. /* vlvsearch is list of dns to VLV Search Specifications */
  236. attrlist_delete( &e->e_attrs, "vlvsearch");
  237. cookie = NULL;
  238. be = slapi_get_first_backend(&cookie);
  239. while (be)
  240. {
  241. if(!be->be_private)
  242. {
  243. /* Generate searches to find the VLV Search Specifications */
  244. int r;
  245. Slapi_PBlock *resultpb= NULL;
  246. Slapi_Entry** entry = NULL;
  247. Slapi_DN dn;
  248. slapi_sdn_init(&dn);
  249. be_getconfigdn(be,&dn);
  250. resultpb= slapi_search_internal( slapi_sdn_get_ndn(&dn), LDAP_SCOPE_ONELEVEL, "objectclass=vlvsearch", NULL, NULL, 1);
  251. slapi_sdn_done(&dn);
  252. slapi_pblock_get( resultpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entry );
  253. slapi_pblock_get( resultpb, SLAPI_PLUGIN_INTOP_RESULT, &r );
  254. if(r==LDAP_SUCCESS)
  255. {
  256. for (; *entry; ++entry)
  257. {
  258. val.bv_val = slapi_entry_get_dn(*entry);
  259. val.bv_len = strlen( val.bv_val );
  260. attrlist_merge( &e->e_attrs, "vlvsearch", vals );
  261. }
  262. }
  263. slapi_free_search_results_internal(resultpb);
  264. slapi_pblock_destroy(resultpb);
  265. }
  266. be = slapi_get_next_backend (cookie);
  267. }
  268. slapi_ch_free ((void **)&cookie);
  269. *returncode= LDAP_SUCCESS;
  270. return SLAPI_DSE_CALLBACK_OK;
  271. }
  272. /*
  273. * Handle a modification request on the root DSE. Only certain
  274. * attributes are writable. If an attempt to modify an attribute
  275. * which is not allowed, return LDAP_UNWILLING_TO_PERFORM, unless
  276. * the modification is disallowed because of ACL checking, in which
  277. * case LDAP_INSUFFICIENT_ACCESS is returned.
  278. */
  279. int
  280. modify_root_dse( Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *e, int *returncode, char *returntext, void *arg )
  281. {
  282. LDAPMod **mods;
  283. /*
  284. * Make a pass through the attributes and check them
  285. * to make sure none are computed. Also check for
  286. * reflected attributes and reject those as well.
  287. * Eventually, some reflected attributes might be
  288. * writable, but for now, none are.
  289. */
  290. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
  291. if ( NULL != mods )
  292. {
  293. int i;
  294. for ( i = 0; NULL != mods[ i ]; i++ )
  295. {
  296. if ( rootdse_is_readonly_attr( mods[ i ]->mod_type ))
  297. {
  298. /* The modification is disallowed */
  299. *returncode = LDAP_UNWILLING_TO_PERFORM;
  300. strcpy(returntext,"Modification of these root DSE attributes not allowed");
  301. return SLAPI_DSE_CALLBACK_ERROR;
  302. }
  303. }
  304. }
  305. *returncode= LDAP_SUCCESS;
  306. return SLAPI_DSE_CALLBACK_OK; /* success -- apply the changes */
  307. }