X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libatalk%2Facl%2Fldap.c;h=f04c5aef1ed106df95247757e97581c08ff86ef5;hb=6a530a4b203eddcbe2dba44a11fa3e3150707b11;hp=e80a6dd63a741d9a855644c944c9f46533e998a4;hpb=2dc4a7b7ba17f4cd3fd33a437f8465cd260fc627;p=netatalk.git diff --git a/libatalk/acl/ldap.c b/libatalk/acl/ldap.c index e80a6dd6..f04c5aef 100644 --- a/libatalk/acl/ldap.c +++ b/libatalk/acl/ldap.c @@ -1,5 +1,4 @@ /* - $Id: ldap.c,v 1.7 2010-04-23 11:37:06 franklahm Exp $ Copyright (c) 2008,2009 Frank Lahm This program is free software; you can redistribute it and/or modify @@ -17,11 +16,15 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#ifdef HAVE_LDAP + #include #include #include #include #include +#include +#define LDAP_DEPRECATED 1 #include #include @@ -47,36 +50,43 @@ int ldap_userscope; char *ldap_groupbase; int ldap_groupscope; char *ldap_uuid_attr; +char *ldap_uuid_string; char *ldap_name_attr; char *ldap_group_attr; char *ldap_uid_attr; +int ldap_uuid_encoding; struct ldap_pref ldap_prefs[] = { - {&ldap_server, "ldap_server", 0, 0, -1}, - {&ldap_auth_method,"ldap_auth_method", 1, 1, -1}, - {&ldap_auth_dn, "ldap_auth_dn", 0, 0, 0}, - {&ldap_auth_pw, "ldap_auth_pw", 0, 0, 0}, - {&ldap_userbase, "ldap_userbase", 0, 0, -1}, - {&ldap_userscope, "ldap_userscope", 1 ,1, -1}, - {&ldap_groupbase, "ldap_groupbase", 0, 0, -1}, - {&ldap_groupscope, "ldap_groupscope", 1 ,1, -1}, - {&ldap_uuid_attr, "ldap_uuid_attr", 0, 0, -1}, - {&ldap_name_attr, "ldap_name_attr", 0, 0, -1}, - {&ldap_group_attr, "ldap_group_attr", 0, 0, -1}, - {&ldap_uid_attr, "ldap_uid_attr", 0, 0, 0}, - {NULL, NULL, 0, 0, -1} + /* pointer to pref, prefname, strorint, intfromarray, valid, valid_save */ + {&ldap_server, "ldap server", 0, 0, -1, -1}, + {&ldap_auth_method, "ldap auth method", 1, 1, -1, -1}, + {&ldap_auth_dn, "ldap auth dn", 0, 0, 0, 0}, + {&ldap_auth_pw, "ldap auth pw", 0, 0, 0, 0}, + {&ldap_userbase, "ldap userbase", 0, 0, -1, -1}, + {&ldap_userscope, "ldap userscope", 1 ,1, -1, -1}, + {&ldap_groupbase, "ldap groupbase", 0, 0, -1, -1}, + {&ldap_groupscope, "ldap groupscope", 1 ,1, -1, -1}, + {&ldap_uuid_attr, "ldap uuid attr", 0, 0, -1, -1}, + {&ldap_uuid_string, "ldap uuid string", 0, 0, 0, 0}, + {&ldap_name_attr, "ldap name attr", 0, 0, -1, -1}, + {&ldap_group_attr, "ldap group attr", 0, 0, -1, -1}, + {&ldap_uid_attr, "ldap uid attr", 0, 0, 0, 0}, + {&ldap_uuid_encoding, "ldap uuid encoding", 1, 1, 0, 0}, + {NULL, NULL, 0, 0, 0, 0} }; struct pref_array prefs_array[] = { - {"ldap_auth_method", "none", LDAP_AUTH_NONE}, - {"ldap_auth_method", "simple", LDAP_AUTH_SIMPLE}, - {"ldap_auth_method", "sasl", LDAP_AUTH_SASL}, - {"ldap_userscope", "base", LDAP_SCOPE_BASE}, - {"ldap_userscope", "one", LDAP_SCOPE_ONELEVEL}, - {"ldap_userscope", "sub", LDAP_SCOPE_SUBTREE}, - {"ldap_groupscope", "base", LDAP_SCOPE_BASE}, - {"ldap_groupscope", "one", LDAP_SCOPE_ONELEVEL}, - {"ldap_groupscope", "sub", LDAP_SCOPE_SUBTREE}, + {"ldap auth method", "none", LDAP_AUTH_NONE}, + {"ldap auth method", "simple", LDAP_AUTH_SIMPLE}, + {"ldap auth method", "sasl", LDAP_AUTH_SASL}, + {"ldap userscope", "base", LDAP_SCOPE_BASE}, + {"ldap userscope", "one", LDAP_SCOPE_ONELEVEL}, + {"ldap userscope", "sub", LDAP_SCOPE_SUBTREE}, + {"ldap groupscope", "base", LDAP_SCOPE_BASE}, + {"ldap groupscope", "one", LDAP_SCOPE_ONELEVEL}, + {"ldap groupscope", "sub", LDAP_SCOPE_SUBTREE}, + {"ldap uuid encoding", "ms-guid", LDAP_UUID_ENCODING_MSGUID}, + {"ldap uuid encoding", "string", LDAP_UUID_ENCODING_STRING}, {NULL, NULL, 0} }; @@ -112,7 +122,7 @@ static int ldap_getattr_fromfilter_withbase_scope( const char *searchbase, static LDAP *ld = NULL; LDAPMessage* msg = NULL; LDAPMessage* entry = NULL; - char **attribute_values = NULL; + struct berval **attribute_values = NULL; struct timeval timeout; LOG(log_maxdebug, logtype_afpd,"ldap: BEGIN"); @@ -157,7 +167,7 @@ retry: } else if (LDAP_AUTH_SIMPLE == ldap_auth_method) { if (ldap_bind_s(ld, ldap_auth_dn, ldap_auth_pw, ldap_auth_method) != LDAP_SUCCESS ) { LOG(log_error, logtype_default, - "ldap: ldap_bind failed: ldap_auth_dn: \'%s\', ldap_auth_pw: \'%s\', ldap_auth_method: \'%d\'"); + "ldap: ldap_bind failed: ldap_auth_dn: \'%s\', ldap_auth_pw: \'%s\', ldap_auth_method: \'%d\'", ldap_auth_dn, ldap_auth_pw, ldap_auth_method); free(ld); ld = NULL; @@ -166,18 +176,17 @@ retry: ldapconnected = 1; } } - /* ldapconnected and ld are now always 1 and != NULL which is important when dealing w. errors*/ LOG(log_maxdebug, logtype_afpd, "ldap: start search: base: %s, filter: %s, attr: %s", searchbase, filter, attributes[0]); /* start LDAP search */ ldaperr = ldap_search_st(ld, searchbase, scope, filter, attributes, 0, &timeout, &msg); - LOG(log_maxdebug, logtype_default, "ldap: ldap_search_st returned: %s, %u", - ldap_err2string(ldaperr), ldaperr); + LOG(log_maxdebug, logtype_default, "ldap: ldap_search_st returned: %s", + ldap_err2string(ldaperr)); if (ldaperr != LDAP_SUCCESS) { - if (retrycount >= 1) - LOG(log_error, logtype_default, "ldap: ldap_search_st failed: %s", ldap_err2string(ldaperr)); + LOG(log_error, logtype_default, "ldap: ldap_search_st failed: %s, retrycount: %i", + ldap_err2string(ldaperr), retrycount); ret = -1; goto cleanup; } @@ -185,7 +194,7 @@ retry: /* parse search result */ LOG(log_maxdebug, logtype_default, "ldap: got %d entries from ldap search", ldap_count_entries(ld, msg)); - if (ldap_count_entries(ld, msg) != 1) { + if ((ret = ldap_count_entries(ld, msg)) != 1) { ret = 0; goto cleanup; } @@ -196,27 +205,30 @@ retry: ret = -1; goto cleanup; } - attribute_values = ldap_get_values(ld, entry, attributes[0]); + + attribute_values = ldap_get_values_len(ld, entry, attributes[0]); if (attribute_values == NULL) { - LOG(log_error, logtype_default, "ldap: ldap_get_values error"); + LOG(log_error, logtype_default, "ldap: ldap_get_values_len error"); ret = -1; goto cleanup; } LOG(log_maxdebug, logtype_afpd,"ldap: search result: %s: %s", - attributes[0], attribute_values[0]); + attributes[0], attribute_values[0]->bv_val); + + /* allocate and copy result */ + *result = calloc(1, attribute_values[0]->bv_len + 1); + memcpy(*result, attribute_values[0]->bv_val, attribute_values[0]->bv_len + 1); - /* allocate result */ - *result = strdup(attribute_values[0]); if (*result == NULL) { - LOG(log_error, logtype_default, "ldap: strdup error: %s",strerror(errno)); + LOG(log_error, logtype_default, "ldap: memcopy error: %s", strerror(errno)); ret = -1; goto cleanup; } cleanup: if (attribute_values) - ldap_value_free(attribute_values); + ldap_value_free_len(attribute_values); /* FIXME: is there another way to free entry ? */ while (entry != NULL) entry = ldap_next_entry(ld, entry); @@ -248,9 +260,16 @@ cleanup: * Interface ********************************************************/ -/* - * returns allocated storage in uuid_string, caller must free it - * returns 0 on success, -1 on error or not found +/*! + * Search UUID for name in LDAP + * + * Caller must free uuid_string when done with it + * + * @param name (r) name to search + * @param type (r) type of USER or GROUP + * @param uuid_string (w) result as pointer to allocated UUID-string + * + * @returns 0 on success, -1 on error or not found */ int ldap_getuuidfromname( const char *name, uuidtype_t type, char **uuid_string) { int ret; @@ -259,6 +278,9 @@ int ldap_getuuidfromname( const char *name, uuidtype_t type, char **uuid_string) char *attributes[] = { ldap_uuid_attr, NULL}; char *ldap_attr; + if (!ldap_config_valid) + return -1; + /* make filter */ if (type == UUID_GROUP) ldap_attr = ldap_group_attr; @@ -275,8 +297,26 @@ int ldap_getuuidfromname( const char *name, uuidtype_t type, char **uuid_string) } else { /* type hopefully == UUID_USER */ ret = ldap_getattr_fromfilter_withbase_scope( ldap_userbase, filter, attributes, ldap_userscope, KEEPALIVE, uuid_string); } + if (ret != 1) return -1; + + if(ldap_uuid_encoding == LDAP_UUID_ENCODING_MSGUID) { + /* Convert byte array to UUID string (no dashes) */ + unsigned char* uuid_bytes = (unsigned char*) *uuid_string; + *uuid_string = malloc(37); + snprintf(*uuid_string, 37, + "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + uuid_bytes[3], uuid_bytes[2], uuid_bytes[1], uuid_bytes[0], /* Data1 */ + uuid_bytes[5], uuid_bytes[4], /* Data2 */ + uuid_bytes[7], uuid_bytes[6], /* Data3 */ + uuid_bytes[8], uuid_bytes[9], /* Data4 - High Bytes */ + uuid_bytes[10], uuid_bytes[11], uuid_bytes[12], /* Data4 - Low Bytes */ + uuid_bytes[13], uuid_bytes[14], uuid_bytes[15]); + free(uuid_bytes); + LOG(log_error, logtype_default, "ldap_getnamefromuuid: uuid_string: %s", *uuid_string); + } + return 0; } @@ -284,15 +324,63 @@ int ldap_getuuidfromname( const char *name, uuidtype_t type, char **uuid_string) * LDAP search wrapper * returns allocated storage in name, caller must free it * returns 0 on success, -1 on error or not found + * + * @param uuidstr (r) uuid to search as ascii string + * @param name (w) return pointer to name as allocated string + * @param type (w) return type: USER or GROUP + * + * returns 0 on success, -1 on errror */ -int ldap_getnamefromuuid( char *uuidstr, char **name, uuidtype_t *type) { +int ldap_getnamefromuuid( const char *uuidstr, char **name, uuidtype_t *type) { int ret; int len; char filter[256]; /* this should really be enough. we dont want to malloc everything! */ char *attributes[] = { NULL, NULL}; - /* make filter */ - len = snprintf( filter, 256, "%s=%s", ldap_uuid_attr, uuidstr); + if (!ldap_config_valid) + return -1; + + if(ldap_uuid_encoding == LDAP_UUID_ENCODING_MSGUID) { + /* Convert to LDAP-safe binary encoding for direct query of AD objectGUID attribute */ + char* stripped = malloc(strlen(uuidstr)); + + int i = 0; + int s = 0; + char c; + while ((c = uuidstr[i])) { + if((c >='a' && c <= 'f') + || (c >= 'A' && c <= 'F') + || (c >= '0' && c <= '9')) { + stripped[s++] = toupper(c); + } + i++; + } + + /* LDAP Binary Notation is \XX * 16 bytes of UUID + terminator = 49 */ + char* ldap_bytes = malloc(49); + snprintf(ldap_bytes, 49, + "\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c" + "\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c", + /* Data1 (uint32) */ + stripped[6], stripped[7], stripped[4], stripped[5], + stripped[2], stripped[3], stripped[0], stripped[1], + /* Data2 (uint16) */ + stripped[10], stripped[11], stripped[8], stripped[9], + /* Data3 (uint16) */ + stripped[14], stripped[15], stripped[12], stripped[13], + /* Data4 (uint64) */ + stripped[16], stripped[17], stripped[18], stripped[19], + stripped[20], stripped[21], stripped[22], stripped[23], + stripped[24], stripped[25], stripped[26], stripped[27], + stripped[28], stripped[29], stripped[30], stripped[31]); + len = snprintf( filter, 256, "%s=%s", ldap_uuid_attr, ldap_bytes); + + free(ldap_bytes); + free(stripped); + } else { + len = snprintf( filter, 256, "%s=%s", ldap_uuid_attr, uuidstr); + } + if (len >= 256 || len == -1) { LOG(log_error, logtype_default, "ldap_getnamefromuuid: filter overflow:%d, \"%s\"", len, filter); return -1; @@ -316,3 +404,4 @@ int ldap_getnamefromuuid( char *uuidstr, char **name, uuidtype_t *type) { return -1; } +#endif /* HAVE_LDAP */