2 Unix SMB/CIFS implementation.
4 DRS::prefixMap implementation
6 Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "dsdb/samdb/samdb.h"
24 #include "librpc/gen_ndr/ndr_drsuapi.h"
25 #include "librpc/gen_ndr/ndr_drsblobs.h"
26 #include "../lib/util/asn1.h"
29 * Initial prefixMap creation according to:
30 * [MS-DRSR] section 5.12.2
32 WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **ppfm)
35 struct dsdb_schema_prefixmap *pfm;
38 const char *oid_prefix;
40 {.id=0x00000000, .oid_prefix="2.5.4"},
41 {.id=0x00000001, .oid_prefix="2.5.6"},
42 {.id=0x00000002, .oid_prefix="1.2.840.113556.1.2"},
43 {.id=0x00000003, .oid_prefix="1.2.840.113556.1.3"},
44 {.id=0x00000004, .oid_prefix="2.16.840.1.101.2.2.1"},
45 {.id=0x00000005, .oid_prefix="2.16.840.1.101.2.2.3"},
46 {.id=0x00000006, .oid_prefix="2.16.840.1.101.2.1.5"},
47 {.id=0x00000007, .oid_prefix="2.16.840.1.101.2.1.4"},
48 {.id=0x00000008, .oid_prefix="2.5.5"},
49 {.id=0x00000009, .oid_prefix="1.2.840.113556.1.4"},
50 {.id=0x0000000A, .oid_prefix="1.2.840.113556.1.5"},
51 {.id=0x00000013, .oid_prefix="0.9.2342.19200300.100"},
52 {.id=0x00000014, .oid_prefix="2.16.840.1.113730.3"},
53 {.id=0x00000015, .oid_prefix="0.9.2342.19200300.100.1"},
54 {.id=0x00000016, .oid_prefix="2.16.840.1.113730.3.1"},
55 {.id=0x00000017, .oid_prefix="1.2.840.113556.1.5.7000"},
56 {.id=0x00000018, .oid_prefix="2.5.21"},
57 {.id=0x00000019, .oid_prefix="2.5.18"},
58 {.id=0x0000001A, .oid_prefix="2.5.20"},
61 /* allocate mem for prefix map */
62 pfm = talloc_zero(mem_ctx, struct dsdb_schema_prefixmap);
63 W_ERROR_HAVE_NO_MEMORY(pfm);
65 pfm->length = ARRAY_SIZE(pfm_init_data);
66 pfm->prefixes = talloc_array(pfm, struct dsdb_schema_prefixmap_oid, pfm->length);
67 W_ERROR_HAVE_NO_MEMORY(pfm->prefixes);
70 for (i = 0; i < pfm->length; i++) {
71 if (!ber_write_partial_OID_String(pfm, &pfm->prefixes[i].bin_oid, pfm_init_data[i].oid_prefix)) {
73 return WERR_INTERNAL_ERROR;
75 pfm->prefixes[i].id = pfm_init_data[i].id;
85 * Adds oid to prefix map.
86 * On success returns ID for newly added index
87 * or ID of existing entry that matches oid
88 * Reference: [MS-DRSR] section 5.12.2
90 * \param pfm prefixMap
91 * \param bin_oid OID prefix to be added to prefixMap
92 * \param pfm_id Location where to store prefixMap entry ID
94 static WERROR _dsdb_schema_pfm_add_entry(struct dsdb_schema_prefixmap *pfm, DATA_BLOB bin_oid, uint32_t *_idx)
97 struct dsdb_schema_prefixmap_oid * pfm_entry;
98 struct dsdb_schema_prefixmap_oid * prefixes_new;
100 /* dup memory for bin-oid prefix to be added */
101 bin_oid = data_blob_dup_talloc(pfm, &bin_oid);
106 /* make room for new entry */
107 prefixes_new = talloc_realloc(pfm, pfm->prefixes, struct dsdb_schema_prefixmap_oid, pfm->length + 1);
109 talloc_free(bin_oid.data);
112 pfm->prefixes = prefixes_new;
114 /* make new unique ID in prefixMap */
115 pfm_entry = &pfm->prefixes[pfm->length];
117 for (i = 0; i < pfm->length; i++) {
118 if (pfm_entry->id < pfm->prefixes[i].id)
119 pfm_entry->id = pfm->prefixes[i].id;
122 /* add new bin-oid prefix */
124 pfm_entry->bin_oid = bin_oid;
134 * Make ATTID for given OID
135 * Reference: [MS-DRSR] section 5.12.2
137 WERROR dsdb_schema_pfm_make_attid(struct dsdb_schema_prefixmap *pfm, const char *oid, uint32_t *attid)
140 uint32_t lo_word, hi_word;
142 const char *last_subid;
144 struct dsdb_schema_prefixmap_oid *pfm_entry;
146 if (!pfm) return WERR_INVALID_PARAMETER;
147 if (!oid) return WERR_INVALID_PARAMETER;
149 /* make last sub-identifier value */
150 last_subid = strrchr(oid, '.');
152 return WERR_INVALID_PARAMETER;
155 last_value = strtoul(last_subid, NULL, 10);
157 /* encode oid in BER format */
158 if (!ber_write_OID_String(pfm, &bin_oid, oid)) {
159 return WERR_INTERNAL_ERROR;
162 /* get the prefix of the OID */
163 if (last_value < 128) {
169 /* search the prefix in the prefix table, if none found, add
170 * one entry for new prefix.
173 for (i = 0; i < pfm->length; i++) {
174 if (pfm->prefixes[i].bin_oid.length != bin_oid.length)
177 if (memcmp(pfm->prefixes[i].bin_oid.data, bin_oid.data, bin_oid.length) == 0) {
178 pfm_entry = &pfm->prefixes[i];
182 /* add entry in no entry exists */
185 WERROR werr = _dsdb_schema_pfm_add_entry(pfm, bin_oid, &idx);
186 W_ERROR_NOT_OK_RETURN(werr);
188 pfm_entry = &pfm->prefixes[idx];
190 /* free memory allocated for bin_oid */
191 data_blob_free(&bin_oid);
194 /* compose the attid */
195 lo_word = last_value % 16384; /* actually get lower 14 bits: lo_word & 0x3FFF */
196 if (last_value >= 16384) {
197 /* mark it so that it is known to not be the whole lastValue
198 * This will raise 16-th bit*/
201 hi_word = pfm_entry->id;
204 * HIWORD is prefixMap id
205 * LOWORD is truncated binary-oid */
206 *attid = (hi_word * 65536) + lo_word;
213 * Make OID for given ATTID.
214 * Reference: [MS-DRSR] section 5.12.2
216 WERROR dsdb_schema_pfm_oid_from_attid(struct dsdb_schema_prefixmap *pfm, uint32_t attid,
217 TALLOC_CTX *mem_ctx, const char **_oid)
220 uint32_t hi_word, lo_word;
221 DATA_BLOB bin_oid = {NULL, 0};
222 struct dsdb_schema_prefixmap_oid *pfm_entry;
223 WERROR werr = WERR_OK;
225 /* crack attid value */
226 hi_word = attid >> 16;
227 lo_word = attid & 0xFFFF;
229 /* locate corRespoNding prefixMap entry */
231 for (i = 0; i < pfm->length; i++) {
232 if (hi_word == pfm->prefixes[i].id) {
233 pfm_entry = &pfm->prefixes[i];
239 return WERR_INTERNAL_ERROR;
242 /* copy oid prefix making enough room */
243 bin_oid.length = pfm_entry->bin_oid.length + 2;
244 bin_oid.data = talloc_array(mem_ctx, uint8_t, bin_oid.length);
245 W_ERROR_HAVE_NO_MEMORY(bin_oid.data);
246 memcpy(bin_oid.data, pfm_entry->bin_oid.data, pfm_entry->bin_oid.length);
249 bin_oid.length = bin_oid.length - 1;
250 bin_oid.data[bin_oid.length-1] = lo_word;
253 if (lo_word >= 32768) {
256 bin_oid.data[bin_oid.length-2] = (0x80 | ((lo_word>>7) & 0x7f));
257 bin_oid.data[bin_oid.length-1] = lo_word & 0x7f;
260 if (!ber_read_OID_String(mem_ctx, bin_oid, _oid)) {
261 werr = WERR_INTERNAL_ERROR;
264 /* free locally allocated memory */
265 talloc_free(bin_oid.data);