s4-test: Move dsdb_schema loading into public function
[nivanova/samba.git] / source4 / torture / drs / drs_util.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    DRSUAPI utility functions to be used in torture tests
5
6    Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
7
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.
12
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.
17
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/>.
20 */
21
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "torture/rpc/drsuapi.h"
26 #include "../lib/util/asn1.h"
27
28 /**
29  * Decode Attribute OID based on MS documentation
30  * See MS-DRSR.pdf - 5.16.4
31  *
32  * On success returns decoded OID and
33  * corresponding prefix_map index (if requested)
34  */
35 bool drs_util_oid_from_attid(struct torture_context *tctx,
36                              const struct drsuapi_DsReplicaOIDMapping_Ctr *prefix_map,
37                              uint32_t attid,
38                              const char **_oid,
39                              int *map_idx)
40 {
41         int i;
42         uint32_t hi_word, lo_word;
43         DATA_BLOB bin_oid = {NULL, 0};
44         struct drsuapi_DsReplicaOIDMapping *map_entry = NULL;
45         TALLOC_CTX *mem_ctx = talloc_named(tctx, 0, "util_drsuapi_oid_from_attid");
46
47         /* crack attid value */
48         hi_word = attid >> 16;
49         lo_word = attid & 0xFFFF;
50
51         /* check last entry in the prefix map is the special one */
52         map_entry = &prefix_map->mappings[prefix_map->num_mappings-1];
53         torture_assert(tctx,
54                         (map_entry->id_prefix == 0)
55                         && (*map_entry->oid.binary_oid == 0xFF),
56                         "Last entry in Prefix Map is not the special one!");
57
58         /* locate corresponding prefixMap entry */
59         map_entry = NULL;
60         for (i = 0; i < prefix_map->num_mappings - 1; i++) {
61
62                 if (hi_word == prefix_map->mappings[i].id_prefix) {
63                         map_entry = &prefix_map->mappings[i];
64                         if (map_idx)    *map_idx = i;
65                         break;
66                 }
67         }
68
69         torture_assert(tctx, map_entry, "Unable to locate corresponding Prefix Map entry");
70
71         /* copy partial oid making enough room */
72         bin_oid.length = map_entry->oid.length + 2;
73         bin_oid.data = talloc_array(mem_ctx, uint8_t, bin_oid.length);
74         torture_assert(tctx, bin_oid.data, "Not enough memory");
75         memcpy(bin_oid.data, map_entry->oid.binary_oid, map_entry->oid.length);
76
77         if (lo_word < 128) {
78                 bin_oid.length = bin_oid.length - 1;
79                 bin_oid.data[bin_oid.length-1] = lo_word;
80         }
81         else {
82                 if (lo_word >= 32768) {
83                         lo_word -= 32768;
84                 }
85                 bin_oid.data[bin_oid.length-2] = ((lo_word / 128) % 128) + 128; // (0x80 | ((lo_word>>7) & 0x7f))
86                 bin_oid.data[bin_oid.length-1] = lo_word % 128; // lo_word & 0x7f
87         }
88
89         torture_assert(tctx,
90                         ber_read_OID_String(tctx, bin_oid, _oid),
91                         "Failed to decode binary OID");
92         talloc_free(mem_ctx);
93
94         return true;
95 }
96
97 /**
98  * Utility function to convert drsuapi_DsAttributeId to String
99  */
100 const char * drs_util_DsAttributeId_to_string(enum drsuapi_DsAttributeId r)
101 {
102         const char *val = NULL;
103
104         switch (r) {
105         case DRSUAPI_ATTRIBUTE_objectClass: val = "DRSUAPI_ATTRIBUTE_objectClass"; break;
106         case DRSUAPI_ATTRIBUTE_description: val = "DRSUAPI_ATTRIBUTE_description"; break;
107         case DRSUAPI_ATTRIBUTE_member: val = "DRSUAPI_ATTRIBUTE_member"; break;
108         case DRSUAPI_ATTRIBUTE_instanceType: val = "DRSUAPI_ATTRIBUTE_instanceType"; break;
109         case DRSUAPI_ATTRIBUTE_whenCreated: val = "DRSUAPI_ATTRIBUTE_whenCreated"; break;
110         case DRSUAPI_ATTRIBUTE_hasMasterNCs: val = "DRSUAPI_ATTRIBUTE_hasMasterNCs"; break;
111         case DRSUAPI_ATTRIBUTE_governsID: val = "DRSUAPI_ATTRIBUTE_governsID"; break;
112         case DRSUAPI_ATTRIBUTE_attributeID: val = "DRSUAPI_ATTRIBUTE_attributeID"; break;
113         case DRSUAPI_ATTRIBUTE_attributeSyntax: val = "DRSUAPI_ATTRIBUTE_attributeSyntax"; break;
114         case DRSUAPI_ATTRIBUTE_isSingleValued: val = "DRSUAPI_ATTRIBUTE_isSingleValued"; break;
115         case DRSUAPI_ATTRIBUTE_rangeLower: val = "DRSUAPI_ATTRIBUTE_rangeLower"; break;
116         case DRSUAPI_ATTRIBUTE_rangeUpper: val = "DRSUAPI_ATTRIBUTE_rangeUpper"; break;
117         case DRSUAPI_ATTRIBUTE_dMDLocation: val = "DRSUAPI_ATTRIBUTE_dMDLocation"; break;
118         case DRSUAPI_ATTRIBUTE_objectVersion: val = "DRSUAPI_ATTRIBUTE_objectVersion"; break;
119         case DRSUAPI_ATTRIBUTE_invocationId: val = "DRSUAPI_ATTRIBUTE_invocationId"; break;
120         case DRSUAPI_ATTRIBUTE_showInAdvancedViewOnly: val = "DRSUAPI_ATTRIBUTE_showInAdvancedViewOnly"; break;
121         case DRSUAPI_ATTRIBUTE_adminDisplayName: val = "DRSUAPI_ATTRIBUTE_adminDisplayName"; break;
122         case DRSUAPI_ATTRIBUTE_adminDescription: val = "DRSUAPI_ATTRIBUTE_adminDescription"; break;
123         case DRSUAPI_ATTRIBUTE_oMSyntax: val = "DRSUAPI_ATTRIBUTE_oMSyntax"; break;
124         case DRSUAPI_ATTRIBUTE_ntSecurityDescriptor: val = "DRSUAPI_ATTRIBUTE_ntSecurityDescriptor"; break;
125         case DRSUAPI_ATTRIBUTE_searchFlags: val = "DRSUAPI_ATTRIBUTE_searchFlags"; break;
126         case DRSUAPI_ATTRIBUTE_lDAPDisplayName: val = "DRSUAPI_ATTRIBUTE_lDAPDisplayName"; break;
127         case DRSUAPI_ATTRIBUTE_name: val = "DRSUAPI_ATTRIBUTE_name"; break;
128         case DRSUAPI_ATTRIBUTE_userAccountControl: val = "DRSUAPI_ATTRIBUTE_userAccountControl"; break;
129         case DRSUAPI_ATTRIBUTE_currentValue: val = "DRSUAPI_ATTRIBUTE_currentValue"; break;
130         case DRSUAPI_ATTRIBUTE_homeDirectory: val = "DRSUAPI_ATTRIBUTE_homeDirectory"; break;
131         case DRSUAPI_ATTRIBUTE_homeDrive: val = "DRSUAPI_ATTRIBUTE_homeDrive"; break;
132         case DRSUAPI_ATTRIBUTE_scriptPath: val = "DRSUAPI_ATTRIBUTE_scriptPath"; break;
133         case DRSUAPI_ATTRIBUTE_profilePath: val = "DRSUAPI_ATTRIBUTE_profilePath"; break;
134         case DRSUAPI_ATTRIBUTE_objectSid: val = "DRSUAPI_ATTRIBUTE_objectSid"; break;
135         case DRSUAPI_ATTRIBUTE_schemaIDGUID: val = "DRSUAPI_ATTRIBUTE_schemaIDGUID"; break;
136         case DRSUAPI_ATTRIBUTE_dBCSPwd: val = "DRSUAPI_ATTRIBUTE_dBCSPwd"; break;
137         case DRSUAPI_ATTRIBUTE_logonHours: val = "DRSUAPI_ATTRIBUTE_logonHours"; break;
138         case DRSUAPI_ATTRIBUTE_userWorkstations: val = "DRSUAPI_ATTRIBUTE_userWorkstations"; break;
139         case DRSUAPI_ATTRIBUTE_unicodePwd: val = "DRSUAPI_ATTRIBUTE_unicodePwd"; break;
140         case DRSUAPI_ATTRIBUTE_ntPwdHistory: val = "DRSUAPI_ATTRIBUTE_ntPwdHistory"; break;
141         case DRSUAPI_ATTRIBUTE_priorValue: val = "DRSUAPI_ATTRIBUTE_priorValue"; break;
142         case DRSUAPI_ATTRIBUTE_supplementalCredentials: val = "DRSUAPI_ATTRIBUTE_supplementalCredentials"; break;
143         case DRSUAPI_ATTRIBUTE_trustAuthIncoming: val = "DRSUAPI_ATTRIBUTE_trustAuthIncoming"; break;
144         case DRSUAPI_ATTRIBUTE_trustAuthOutgoing: val = "DRSUAPI_ATTRIBUTE_trustAuthOutgoing"; break;
145         case DRSUAPI_ATTRIBUTE_lmPwdHistory: val = "DRSUAPI_ATTRIBUTE_lmPwdHistory"; break;
146         case DRSUAPI_ATTRIBUTE_sAMAccountName: val = "DRSUAPI_ATTRIBUTE_sAMAccountName"; break;
147         case DRSUAPI_ATTRIBUTE_sAMAccountType: val = "DRSUAPI_ATTRIBUTE_sAMAccountType"; break;
148         case DRSUAPI_ATTRIBUTE_fSMORoleOwner: val = "DRSUAPI_ATTRIBUTE_fSMORoleOwner"; break;
149         case DRSUAPI_ATTRIBUTE_systemFlags: val = "DRSUAPI_ATTRIBUTE_systemFlags"; break;
150         case DRSUAPI_ATTRIBUTE_serverReference: val = "DRSUAPI_ATTRIBUTE_serverReference"; break;
151         case DRSUAPI_ATTRIBUTE_serverReferenceBL: val = "DRSUAPI_ATTRIBUTE_serverReferenceBL"; break;
152         case DRSUAPI_ATTRIBUTE_initialAuthIncoming: val = "DRSUAPI_ATTRIBUTE_initialAuthIncoming"; break;
153         case DRSUAPI_ATTRIBUTE_initialAuthOutgoing: val = "DRSUAPI_ATTRIBUTE_initialAuthOutgoing"; break;
154         case DRSUAPI_ATTRIBUTE_wellKnownObjects: val = "DRSUAPI_ATTRIBUTE_wellKnownObjects"; break;
155         case DRSUAPI_ATTRIBUTE_dNSHostName: val = "DRSUAPI_ATTRIBUTE_dNSHostName"; break;
156         case DRSUAPI_ATTRIBUTE_isMemberOfPartialAttributeSet: val = "DRSUAPI_ATTRIBUTE_isMemberOfPartialAttributeSet"; break;
157         case DRSUAPI_ATTRIBUTE_userPrincipalName: val = "DRSUAPI_ATTRIBUTE_userPrincipalName"; break;
158         case DRSUAPI_ATTRIBUTE_groupType: val = "DRSUAPI_ATTRIBUTE_groupType"; break;
159         case DRSUAPI_ATTRIBUTE_servicePrincipalName: val = "DRSUAPI_ATTRIBUTE_servicePrincipalName"; break;
160         case DRSUAPI_ATTRIBUTE_objectCategory: val = "DRSUAPI_ATTRIBUTE_objectCategory"; break;
161         case DRSUAPI_ATTRIBUTE_gPLink: val = "DRSUAPI_ATTRIBUTE_gPLink"; break;
162         case DRSUAPI_ATTRIBUTE_msDS_Behavior_Version: val = "DRSUAPI_ATTRIBUTE_msDS_Behavior_Version"; break;
163         case DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber: val = "DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber"; break;
164         case DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs: val = "DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs"; break;
165         case DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs: val = "DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs"; break;
166         default: val = "UNKNOWN_ENUM_VALUE"; break;
167         }
168         return val;
169 }
170
171
172 /**
173  * Loads dsdb_schema from ldb connection using remote prefixMap.
174  * Schema will be loaded only if:
175  *  - ldb has no attached schema
176  *  - reload_schema is true
177  *
178  * This function is to be used in tests that use GetNCChanges() function
179  */
180 bool drs_util_dsdb_schema_load_ldb(struct torture_context *tctx,
181                                    struct ldb_context *ldb,
182                                    const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr,
183                                    bool reload_schema)
184 {
185         int i, ret;
186         WERROR werr;
187         const char *err_msg;
188         struct ldb_result *a_res;
189         struct ldb_result *c_res;
190         struct ldb_dn *schema_dn;
191         struct dsdb_schema *ldap_schema;
192
193         ldap_schema = dsdb_get_schema(ldb, NULL);
194         if (ldap_schema && !reload_schema) {
195                 return true;
196         }
197
198         schema_dn = ldb_get_schema_basedn(ldb);
199         torture_assert(tctx, schema_dn != NULL,
200                        talloc_asprintf(tctx, "ldb_get_schema_basedn() failed: %s", ldb_errstring(ldb)));
201
202         ldap_schema = dsdb_new_schema(ldb);
203         torture_assert(tctx, ldap_schema != NULL, "dsdb_new_schema() failed!");
204
205         werr = dsdb_load_prefixmap_from_drsuapi(ldap_schema, mapping_ctr);
206
207         /*
208          * load the attribute definitions
209          */
210         ret = ldb_search(ldb, ldap_schema, &a_res,
211                          schema_dn, LDB_SCOPE_ONELEVEL, NULL,
212                          "(objectClass=attributeSchema)");
213         if (ret != LDB_SUCCESS) {
214                 err_msg = talloc_asprintf(tctx,
215                                           "failed to search attributeSchema objects: %s",
216                                           ldb_errstring(ldb));
217                 torture_fail(tctx, err_msg);
218         }
219
220         /*
221          * load the objectClass definitions
222          */
223         ret = ldb_search(ldb, ldap_schema, &c_res,
224                          schema_dn, LDB_SCOPE_ONELEVEL, NULL,
225                          "(objectClass=classSchema)");
226         if (ret != LDB_SUCCESS) {
227                 err_msg = talloc_asprintf(tctx,
228                                           "failed to search classSchema objects: %s",
229                                           ldb_errstring(ldb));
230                 torture_fail(tctx, err_msg);
231         }
232
233         /* Build schema */
234         for (i=0; i < a_res->count; i++) {
235                 werr = dsdb_attribute_from_ldb(ldb, ldap_schema, a_res->msgs[i]);
236                 torture_assert_werr_ok(tctx, werr,
237                                        talloc_asprintf(tctx,
238                                                        "dsdb_attribute_from_ldb() failed for: %s",
239                                                        ldb_dn_get_linearized(a_res->msgs[i]->dn)));
240         }
241
242         for (i=0; i < c_res->count; i++) {
243                 werr = dsdb_class_from_ldb(ldap_schema, c_res->msgs[i]);
244                 torture_assert_werr_ok(tctx, werr,
245                                        talloc_asprintf(tctx,
246                                                        "dsdb_class_from_ldb() failed for: %s",
247                                                        ldb_dn_get_linearized(c_res->msgs[i]->dn)));
248         }
249
250         talloc_free(a_res);
251         talloc_free(c_res);
252
253         ret = dsdb_set_schema(ldb, ldap_schema);
254         if (ret != LDB_SUCCESS) {
255                 torture_fail(tctx,
256                              talloc_asprintf(tctx, "dsdb_set_schema() failed: %s", ldb_strerror(ret)));
257         }
258
259         return true;
260 }