#include <sys/time.h>
#include <string.h>
#include <errno.h>
+#include <ctype.h>
#define LDAP_DEPRECATED 1
#include <ldap.h>
#include <atalk/afp.h>
#include <atalk/uuid.h>
#include <atalk/ldapconfig.h> /* For struct ldap_pref */
+#include <atalk/errchk.h>
typedef enum {
KEEPALIVE = 1
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;
+char *ldap_userfilter;
+char *ldap_groupfilter;
+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},
+ {&ldap_userfilter, "ldap user filter", 0, 0, 0, 0},
+ {&ldap_groupfilter, "ldap group filter", 0, 0, 0, 0},
+ {&ldap_auth_pw, "ldap auth pw", 0, 0, 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}
};
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");
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);
return ret;
}
+/*!
+ * Generate LDAP filter string for UUID query
+
+ * @param[in] uuidstr the UUID as string
+ * @param[in] attr_filter optional attribute
+ * @returns pointer to static filter string
+ */
+static char *gen_uuid_filter(const char *uuidstr_in, const char *attr_filter)
+{
+ EC_INIT;
+ int len;
+ const char *uuidstr = uuidstr_in;
+
+#define MAX_FILTER_SIZE 512
+ static char filter[MAX_FILTER_SIZE];
+ char stripped[MAX_FILTER_SIZE];
+
+#define LDAP_BIN_UUID_LEN 49 /* LDAP Binary Notation is \XX * 16 bytes of UUID + terminator = 49 */
+ char ldap_bytes[LDAP_BIN_UUID_LEN];
+
+ if (ldap_uuid_encoding == LDAP_UUID_ENCODING_MSGUID) {
+ /* Convert to LDAP-safe binary encoding for direct query of AD objectGUID attribute */
+ int i = 0, 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++;
+ }
+
+ snprintf(ldap_bytes, LDAP_BIN_UUID_LEN,
+ "\\%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]);
+ uuidstr = ldap_bytes;
+ }
+
+ if (attr_filter) {
+ len = snprintf(filter, 256, "(&(%s=%s)(%s))", ldap_uuid_attr, uuidstr, attr_filter);
+ } else {
+ len = snprintf(filter, 256, "%s=%s", ldap_uuid_attr, uuidstr);
+ }
+
+EC_CLEANUP:
+ if (ret != 0)
+ return NULL;
+ return filter;
+}
+
/********************************************************
* Interface
********************************************************/
} 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;
}
* returns 0 on success, -1 on errror
*/
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! */
+ EC_INIT;
+ char *filter;
char *attributes[] = { NULL, NULL};
if (!ldap_config_valid)
- return -1;
+ EC_FAIL;
+
+ /*
+ * Search groups first as group acls are probably used more often.
+ * Note the special case of AD where users and groups are stored
+ * under the same subtree.
+ */
- /* make filter */
- 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;
- }
- /* search groups first. group acls are probably used more often */
attributes[0] = ldap_group_attr;
- ret = ldap_getattr_fromfilter_withbase_scope( ldap_groupbase, filter, attributes, ldap_groupscope, KEEPALIVE, name);
- if (ret == -1)
- return -1;
+ EC_NULL( filter = gen_uuid_filter(uuidstr, ldap_groupfilter) );
+ EC_NEG1( ret = ldap_getattr_fromfilter_withbase_scope(
+ ldap_groupbase,
+ filter,
+ attributes,
+ ldap_groupscope,
+ KEEPALIVE,
+ name) );
if (ret == 1) {
*type = UUID_GROUP;
- return 0;
+ EC_EXIT_STATUS(0);
}
attributes[0] = ldap_name_attr;
- ret = ldap_getattr_fromfilter_withbase_scope( ldap_userbase, filter, attributes, ldap_userscope, KEEPALIVE, name);
+ EC_NULL( filter = gen_uuid_filter(uuidstr, ldap_userfilter) );
+ EC_NEG1( ret = ldap_getattr_fromfilter_withbase_scope(
+ ldap_userbase,
+ filter,
+ attributes,
+ ldap_userscope,
+ KEEPALIVE,
+ name) );
if (ret == 1) {
*type = UUID_USER;
- return 0;
+ EC_EXIT_STATUS(0);
}
- return -1;
+ EC_FAIL;
+
+EC_CLEANUP:
+ EC_EXIT;
}
#endif /* HAVE_LDAP */