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 partial binary OID for supplied OID.
135 * Reference: [MS-DRSR] section 5.12.2
137 static WERROR
_dsdb_pfm_make_binary_oid(const char *full_oid
, TALLOC_CTX
*mem_ctx
,
138 DATA_BLOB
*_bin_oid
, uint32_t *_last_subid
)
141 const char *oid_subid
;
143 /* make last sub-identifier value */
144 oid_subid
= strrchr(full_oid
, '.');
146 return WERR_INVALID_PARAMETER
;
149 last_subid
= strtoul(oid_subid
, NULL
, 10);
151 /* encode oid in BER format */
152 if (!ber_write_OID_String(mem_ctx
, _bin_oid
, full_oid
)) {
153 return WERR_INTERNAL_ERROR
;
156 /* get the prefix of the OID */
157 if (last_subid
< 128) {
158 _bin_oid
->length
-= 1;
160 _bin_oid
->length
-= 2;
163 /* return last_value if requested */
165 *_last_subid
= last_subid
;
172 * Lookup partial-binary-oid in prefixMap
174 WERROR
dsdb_schema_pfm_find_binary_oid(struct dsdb_schema_prefixmap
*pfm
,
180 for (i
= 0; i
< pfm
->length
; i
++) {
181 if (pfm
->prefixes
[i
].bin_oid
.length
!= bin_oid
.length
) {
185 if (memcmp(pfm
->prefixes
[i
].bin_oid
.data
, bin_oid
.data
, bin_oid
.length
) == 0) {
193 return WERR_DS_NO_MSDS_INTID
;
197 * Make ATTID for given OID
198 * Reference: [MS-DRSR] section 5.12.2
200 WERROR
dsdb_schema_pfm_make_attid(struct dsdb_schema_prefixmap
*pfm
, const char *oid
, uint32_t *attid
)
204 uint32_t lo_word
, hi_word
;
209 return WERR_INVALID_PARAMETER
;
212 return WERR_INVALID_PARAMETER
;
215 werr
= _dsdb_pfm_make_binary_oid(oid
, pfm
, &bin_oid
, &last_subid
);
216 W_ERROR_NOT_OK_RETURN(werr
);
218 /* search the prefix in the prefix table, if none found, add
219 * one entry for new prefix.
221 werr
= dsdb_schema_pfm_find_binary_oid(pfm
, bin_oid
, &idx
);
222 if (W_ERROR_IS_OK(werr
)) {
223 /* free memory allocated for bin_oid */
224 data_blob_free(&bin_oid
);
226 /* entry does not exists, add it */
227 werr
= _dsdb_schema_pfm_add_entry(pfm
, bin_oid
, &idx
);
228 W_ERROR_NOT_OK_RETURN(werr
);
231 /* compose the attid */
232 lo_word
= last_subid
% 16384; /* actually get lower 14 bits: lo_word & 0x3FFF */
233 if (last_subid
>= 16384) {
234 /* mark it so that it is known to not be the whole lastValue
235 * This will raise 16-th bit*/
238 hi_word
= pfm
->prefixes
[idx
].id
;
241 * HIWORD is prefixMap id
242 * LOWORD is truncated binary-oid */
243 *attid
= (hi_word
* 65536) + lo_word
;
250 * Make OID for given ATTID.
251 * Reference: [MS-DRSR] section 5.12.2
253 WERROR
dsdb_schema_pfm_oid_from_attid(struct dsdb_schema_prefixmap
*pfm
, uint32_t attid
,
254 TALLOC_CTX
*mem_ctx
, const char **_oid
)
257 uint32_t hi_word
, lo_word
;
258 DATA_BLOB bin_oid
= {NULL
, 0};
259 struct dsdb_schema_prefixmap_oid
*pfm_entry
;
260 WERROR werr
= WERR_OK
;
262 /* crack attid value */
263 hi_word
= attid
>> 16;
264 lo_word
= attid
& 0xFFFF;
266 /* locate corRespoNding prefixMap entry */
268 for (i
= 0; i
< pfm
->length
; i
++) {
269 if (hi_word
== pfm
->prefixes
[i
].id
) {
270 pfm_entry
= &pfm
->prefixes
[i
];
276 return WERR_INTERNAL_ERROR
;
279 /* copy oid prefix making enough room */
280 bin_oid
.length
= pfm_entry
->bin_oid
.length
+ 2;
281 bin_oid
.data
= talloc_array(mem_ctx
, uint8_t, bin_oid
.length
);
282 W_ERROR_HAVE_NO_MEMORY(bin_oid
.data
);
283 memcpy(bin_oid
.data
, pfm_entry
->bin_oid
.data
, pfm_entry
->bin_oid
.length
);
286 bin_oid
.length
= bin_oid
.length
- 1;
287 bin_oid
.data
[bin_oid
.length
-1] = lo_word
;
290 if (lo_word
>= 32768) {
293 bin_oid
.data
[bin_oid
.length
-2] = (0x80 | ((lo_word
>>7) & 0x7f));
294 bin_oid
.data
[bin_oid
.length
-1] = lo_word
& 0x7f;
297 if (!ber_read_OID_String(mem_ctx
, bin_oid
, _oid
)) {
298 werr
= WERR_INTERNAL_ERROR
;
301 /* free locally allocated memory */
302 talloc_free(bin_oid
.data
);