1/* 2 Unix SMB/CIFS implementation. 3 ads (active directory) utility library 4 Copyright (C) Guenther Deschner 2005-2007 5 Copyright (C) Gerald (Jerry) Carter 2006 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22 23#ifdef HAVE_LDAP 24 25ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, 26 const char *schema_path, 27 const char **OIDs, size_t num_OIDs, 28 char ***OIDs_out, char ***names, size_t *count) 29{ 30 ADS_STATUS status; 31 LDAPMessage *res = NULL; 32 LDAPMessage *msg; 33 char *expr = NULL; 34 const char *attrs[] = { "lDAPDisplayName", "attributeId", NULL }; 35 int i = 0, p = 0; 36 37 if (!ads || !mem_ctx || !names || !count || !OIDs || !OIDs_out) { 38 return ADS_ERROR(LDAP_PARAM_ERROR); 39 } 40 41 if (num_OIDs == 0 || OIDs[0] == NULL) { 42 return ADS_ERROR_NT(NT_STATUS_NONE_MAPPED); 43 } 44 45 if ((expr = talloc_asprintf(mem_ctx, "(|")) == NULL) { 46 return ADS_ERROR(LDAP_NO_MEMORY); 47 } 48 49 for (i=0; i<num_OIDs; i++) { 50 51 if ((expr = talloc_asprintf_append_buffer(expr, "(attributeId=%s)", 52 OIDs[i])) == NULL) { 53 return ADS_ERROR(LDAP_NO_MEMORY); 54 } 55 } 56 57 if ((expr = talloc_asprintf_append_buffer(expr, ")")) == NULL) { 58 return ADS_ERROR(LDAP_NO_MEMORY); 59 } 60 61 status = ads_do_search_retry(ads, schema_path, 62 LDAP_SCOPE_SUBTREE, expr, attrs, &res); 63 if (!ADS_ERR_OK(status)) { 64 return status; 65 } 66 67 *count = ads_count_replies(ads, res); 68 if (*count == 0 || !res) { 69 status = ADS_ERROR_NT(NT_STATUS_NONE_MAPPED); 70 goto out; 71 } 72 73 if (((*names) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) { 74 status = ADS_ERROR(LDAP_NO_MEMORY); 75 goto out; 76 } 77 if (((*OIDs_out) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) { 78 status = ADS_ERROR(LDAP_NO_MEMORY); 79 goto out; 80 } 81 82 for (msg = ads_first_entry(ads, res); msg != NULL; 83 msg = ads_next_entry(ads, msg)) { 84 85 (*names)[p] = ads_pull_string(ads, mem_ctx, msg, 86 "lDAPDisplayName"); 87 (*OIDs_out)[p] = ads_pull_string(ads, mem_ctx, msg, 88 "attributeId"); 89 if (((*names)[p] == NULL) || ((*OIDs_out)[p] == NULL)) { 90 status = ADS_ERROR(LDAP_NO_MEMORY); 91 goto out; 92 } 93 94 p++; 95 } 96 97 if (*count < num_OIDs) { 98 status = ADS_ERROR_NT(STATUS_SOME_UNMAPPED); 99 goto out; 100 } 101 102 status = ADS_ERROR(LDAP_SUCCESS); 103out: 104 ads_msgfree(ads, res); 105 106 return status; 107} 108 109const char *ads_get_attrname_by_guid(ADS_STRUCT *ads, 110 const char *schema_path, 111 TALLOC_CTX *mem_ctx, 112 const struct GUID *schema_guid) 113{ 114 ADS_STATUS rc; 115 LDAPMessage *res = NULL; 116 char *expr = NULL; 117 const char *attrs[] = { "lDAPDisplayName", NULL }; 118 const char *result = NULL; 119 char *guid_bin = NULL; 120 121 if (!ads || !mem_ctx || !schema_guid) { 122 goto done; 123 } 124 125 guid_bin = guid_binstring(mem_ctx, schema_guid); 126 if (!guid_bin) { 127 goto done; 128 } 129 130 expr = talloc_asprintf(mem_ctx, "(schemaIDGUID=%s)", guid_bin); 131 if (!expr) { 132 goto done; 133 } 134 135 rc = ads_do_search_retry(ads, schema_path, LDAP_SCOPE_SUBTREE, 136 expr, attrs, &res); 137 if (!ADS_ERR_OK(rc)) { 138 goto done; 139 } 140 141 if (ads_count_replies(ads, res) != 1) { 142 goto done; 143 } 144 145 result = ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName"); 146 147 done: 148 TALLOC_FREE(guid_bin); 149 ads_msgfree(ads, res); 150 return result; 151 152} 153 154const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, const char *schema_path, TALLOC_CTX *mem_ctx, const char * OID) 155{ 156 ADS_STATUS rc; 157 int count = 0; 158 LDAPMessage *res = NULL; 159 char *expr = NULL; 160 const char *attrs[] = { "lDAPDisplayName", NULL }; 161 char *result; 162 163 if (ads == NULL || mem_ctx == NULL || OID == NULL) { 164 goto failed; 165 } 166 167 expr = talloc_asprintf(mem_ctx, "(attributeId=%s)", OID); 168 if (expr == NULL) { 169 goto failed; 170 } 171 172 rc = ads_do_search_retry(ads, schema_path, LDAP_SCOPE_SUBTREE, 173 expr, attrs, &res); 174 if (!ADS_ERR_OK(rc)) { 175 goto failed; 176 } 177 178 count = ads_count_replies(ads, res); 179 if (count == 0 || !res) { 180 goto failed; 181 } 182 183 result = ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName"); 184 ads_msgfree(ads, res); 185 186 return result; 187 188failed: 189 DEBUG(0,("ads_get_attrname_by_oid: failed to retrieve name for oid: %s\n", 190 OID)); 191 192 ads_msgfree(ads, res); 193 return NULL; 194} 195/********************************************************************* 196*********************************************************************/ 197 198ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path) 199{ 200 ADS_STATUS status; 201 LDAPMessage *res; 202 const char *schema; 203 const char *attrs[] = { "schemaNamingContext", NULL }; 204 205 status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); 206 if (!ADS_ERR_OK(status)) { 207 return status; 208 } 209 210 if ( (schema = ads_pull_string(ads, mem_ctx, res, "schemaNamingContext")) == NULL ) { 211 ads_msgfree(ads, res); 212 return ADS_ERROR(LDAP_NO_RESULTS_RETURNED); 213 } 214 215 if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) { 216 ads_msgfree(ads, res); 217 return ADS_ERROR(LDAP_NO_MEMORY); 218 } 219 220 ads_msgfree(ads, res); 221 222 return status; 223} 224 225/** 226 * Check for "Services for Unix" or rfc2307 Schema and load some attributes into the ADS_STRUCT 227 * @param ads connection to ads server 228 * @param enum mapping type 229 * @return ADS_STATUS status of search (False if one or more attributes couldn't be 230 * found in Active Directory) 231 **/ 232ADS_STATUS ads_check_posix_schema_mapping(TALLOC_CTX *mem_ctx, 233 ADS_STRUCT *ads, 234 enum wb_posix_mapping map_type, 235 struct posix_schema **s ) 236{ 237 TALLOC_CTX *ctx = NULL; 238 ADS_STATUS status; 239 char **oids_out, **names_out; 240 size_t num_names; 241 char *schema_path = NULL; 242 int i; 243 struct posix_schema *schema = NULL; 244 245 const char *oids_sfu[] = { ADS_ATTR_SFU_UIDNUMBER_OID, 246 ADS_ATTR_SFU_GIDNUMBER_OID, 247 ADS_ATTR_SFU_HOMEDIR_OID, 248 ADS_ATTR_SFU_SHELL_OID, 249 ADS_ATTR_SFU_GECOS_OID, 250 ADS_ATTR_SFU_UID_OID }; 251 252 const char *oids_sfu20[] = { ADS_ATTR_SFU20_UIDNUMBER_OID, 253 ADS_ATTR_SFU20_GIDNUMBER_OID, 254 ADS_ATTR_SFU20_HOMEDIR_OID, 255 ADS_ATTR_SFU20_SHELL_OID, 256 ADS_ATTR_SFU20_GECOS_OID, 257 ADS_ATTR_SFU20_UID_OID }; 258 259 const char *oids_rfc2307[] = { ADS_ATTR_RFC2307_UIDNUMBER_OID, 260 ADS_ATTR_RFC2307_GIDNUMBER_OID, 261 ADS_ATTR_RFC2307_HOMEDIR_OID, 262 ADS_ATTR_RFC2307_SHELL_OID, 263 ADS_ATTR_RFC2307_GECOS_OID, 264 ADS_ATTR_RFC2307_UID_OID }; 265 266 DEBUG(10,("ads_check_posix_schema_mapping for schema mode: %d\n", map_type)); 267 268 switch (map_type) { 269 270 case WB_POSIX_MAP_TEMPLATE: 271 case WB_POSIX_MAP_UNIXINFO: 272 DEBUG(10,("ads_check_posix_schema_mapping: nothing to do\n")); 273 return ADS_ERROR(LDAP_SUCCESS); 274 275 case WB_POSIX_MAP_SFU: 276 case WB_POSIX_MAP_SFU20: 277 case WB_POSIX_MAP_RFC2307: 278 break; 279 280 default: 281 DEBUG(0,("ads_check_posix_schema_mapping: " 282 "unknown enum %d\n", map_type)); 283 return ADS_ERROR(LDAP_PARAM_ERROR); 284 } 285 286 if ( (ctx = talloc_init("ads_check_posix_schema_mapping")) == NULL ) { 287 return ADS_ERROR(LDAP_NO_MEMORY); 288 } 289 290 if ( (schema = TALLOC_P(mem_ctx, struct posix_schema)) == NULL ) { 291 TALLOC_FREE( ctx ); 292 return ADS_ERROR(LDAP_NO_MEMORY); 293 } 294 295 status = ads_schema_path(ads, ctx, &schema_path); 296 if (!ADS_ERR_OK(status)) { 297 DEBUG(3,("ads_check_posix_mapping: Unable to retrieve schema DN!\n")); 298 goto done; 299 } 300 301 switch (map_type) { 302 case WB_POSIX_MAP_SFU: 303 status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu, 304 ARRAY_SIZE(oids_sfu), 305 &oids_out, &names_out, &num_names); 306 break; 307 case WB_POSIX_MAP_SFU20: 308 status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu20, 309 ARRAY_SIZE(oids_sfu20), 310 &oids_out, &names_out, &num_names); 311 break; 312 case WB_POSIX_MAP_RFC2307: 313 status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_rfc2307, 314 ARRAY_SIZE(oids_rfc2307), 315 &oids_out, &names_out, &num_names); 316 break; 317 default: 318 status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); 319 break; 320 } 321 322 if (!ADS_ERR_OK(status)) { 323 DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n", 324 ads_errstr(status))); 325 goto done; 326 } 327 328 for (i=0; i<num_names; i++) { 329 330 DEBUGADD(10,("\tOID %s has name: %s\n", oids_out[i], names_out[i])); 331 332 if (strequal(ADS_ATTR_RFC2307_UIDNUMBER_OID, oids_out[i]) || 333 strequal(ADS_ATTR_SFU_UIDNUMBER_OID, oids_out[i]) || 334 strequal(ADS_ATTR_SFU20_UIDNUMBER_OID, oids_out[i])) { 335 schema->posix_uidnumber_attr = talloc_strdup(schema, names_out[i]); 336 continue; 337 } 338 339 if (strequal(ADS_ATTR_RFC2307_GIDNUMBER_OID, oids_out[i]) || 340 strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i]) || 341 strequal(ADS_ATTR_SFU20_GIDNUMBER_OID, oids_out[i])) { 342 schema->posix_gidnumber_attr = talloc_strdup(schema, names_out[i]); 343 continue; 344 } 345 346 if (strequal(ADS_ATTR_RFC2307_HOMEDIR_OID, oids_out[i]) || 347 strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i]) || 348 strequal(ADS_ATTR_SFU20_HOMEDIR_OID, oids_out[i])) { 349 schema->posix_homedir_attr = talloc_strdup(schema, names_out[i]); 350 continue; 351 } 352 353 if (strequal(ADS_ATTR_RFC2307_SHELL_OID, oids_out[i]) || 354 strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i]) || 355 strequal(ADS_ATTR_SFU20_SHELL_OID, oids_out[i])) { 356 schema->posix_shell_attr = talloc_strdup(schema, names_out[i]); 357 continue; 358 } 359 360 if (strequal(ADS_ATTR_RFC2307_GECOS_OID, oids_out[i]) || 361 strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i]) || 362 strequal(ADS_ATTR_SFU20_GECOS_OID, oids_out[i])) { 363 schema->posix_gecos_attr = talloc_strdup(schema, names_out[i]); 364 } 365 366 if (strequal(ADS_ATTR_RFC2307_UID_OID, oids_out[i]) || 367 strequal(ADS_ATTR_SFU_UID_OID, oids_out[i]) || 368 strequal(ADS_ATTR_SFU20_UID_OID, oids_out[i])) { 369 schema->posix_uid_attr = talloc_strdup(schema, names_out[i]); 370 } 371 } 372 373 if (!schema->posix_uidnumber_attr || 374 !schema->posix_gidnumber_attr || 375 !schema->posix_homedir_attr || 376 !schema->posix_shell_attr || 377 !schema->posix_gecos_attr) { 378 status = ADS_ERROR(LDAP_NO_MEMORY); 379 TALLOC_FREE( schema ); 380 goto done; 381 } 382 383 *s = schema; 384 385 status = ADS_ERROR(LDAP_SUCCESS); 386 387done: 388 TALLOC_FREE(ctx); 389 390 return status; 391} 392 393#endif 394