src/server/daemon/ldap_auth.c

changeset 470
467ed0f559af
parent 469
9a36a6b52e4c
child 471
9aa5ae3258f5
equal deleted inserted replaced
469:9a36a6b52e4c 470:467ed0f559af
55 static LDAPConfig ws_ldap_default_config = { 55 static LDAPConfig ws_ldap_default_config = {
56 NULL, // resource 56 NULL, // resource
57 NULL, // basedn 57 NULL, // basedn
58 NULL, // binddn 58 NULL, // binddn
59 NULL, // bindpw 59 NULL, // bindpw
60 "(&(objectclass=inetorgperson)(!(cn=%s)(uid=%s)))", // userSearchFilter 60 "(&(objectclass=inetorgperson)(|(cn=%s)(uid=%s)))", // userSearchFilter
61 ws_ldap_default_uid_attr, // uidAttributes 61 ws_ldap_default_uid_attr, // uidAttributes
62 1, // numUidAttributes 62 1, // numUidAttributes
63 "(&(|(objectclass=groupOfNames)(objectclass=groupOfUniqueNames))(cn=%s))", // groupSearchFilter 63 "(&(|(objectclass=groupOfNames)(objectclass=groupOfUniqueNames))(cn=%s))", // groupSearchFilter
64 ws_ldap_default_member_attr, // memberAttributes 64 ws_ldap_default_member_attr, // memberAttributes
65 2, // numMemberAttributes 65 2, // numMemberAttributes
81 static LDAPConfig ws_ldap_ad_config = { 81 static LDAPConfig ws_ldap_ad_config = {
82 NULL, // resource 82 NULL, // resource
83 NULL, // basedn 83 NULL, // basedn
84 NULL, // binddn 84 NULL, // binddn
85 NULL, // bindpw 85 NULL, // bindpw
86 "(&(objectclass=inetorgperson)(!(cn=%s)(uid=%s)))", // userSearchFilter 86 "(&(objectclass=inetorgperson)(|(cn=%s)(uid=%s)))", // userSearchFilter
87 ws_ad_default_uid_attr, // uidAttributes 87 ws_ad_default_uid_attr, // uidAttributes
88 1, // numUidAttributes 88 1, // numUidAttributes
89 "", // groupSearchFilter 89 "", // groupSearchFilter
90 ws_ad_default_member_attr, // memberAttributes 90 ws_ad_default_member_attr, // memberAttributes
91 2, // numMemberAttributes 91 2, // numMemberAttributes
155 cxstring uidAttributes = serverconfig_object_directive_value(node, cx_str("UidAttributes")); 155 cxstring uidAttributes = serverconfig_object_directive_value(node, cx_str("UidAttributes"));
156 cxstring groupSearchFilter = serverconfig_object_directive_value(node, cx_str("GroupSearchFilter")); 156 cxstring groupSearchFilter = serverconfig_object_directive_value(node, cx_str("GroupSearchFilter"));
157 cxstring memberAttributes = serverconfig_object_directive_value(node, cx_str("MemberAttributes")); 157 cxstring memberAttributes = serverconfig_object_directive_value(node, cx_str("MemberAttributes"));
158 cxstring memberType = serverconfig_object_directive_value(node, cx_str("MemberType")); 158 cxstring memberType = serverconfig_object_directive_value(node, cx_str("MemberType"));
159 cxstring enableGroups = serverconfig_object_directive_value(node, cx_str("EnableGroups")); 159 cxstring enableGroups = serverconfig_object_directive_value(node, cx_str("EnableGroups"));
160 cxstring userNameIsDn = serverconfig_object_directive_value(node, cx_str("UserNameIsDn")); 160 cxstring userNameIsDn = serverconfig_object_directive_value(node, cx_str("UserNameIsDn"));
161 161
162 if(!resource.ptr) { 162 if(!resource.ptr) {
163 // TODO: create resource pool 163 // TODO: create resource pool
164 } else { 164 } else {
165 authdb->config.resource = resource.ptr; 165 authdb->config.resource = cx_strdup_a(cfg->a, resource).ptr;
166 if(!authdb->config.resource) return NULL;
166 } 167 }
167 168
168 if(!basedn.ptr) { 169 if(!basedn.ptr) {
169 log_ereport(LOG_FAILURE, "ldap authdb %s: basedn is required", name); 170 log_ereport(LOG_FAILURE, "ldap authdb %s: basedn is required", name);
170 return NULL; 171 return NULL;
171 } 172 }
172 authdb->config.basedn = basedn.ptr; 173 authdb->config.basedn = cx_strdup_a(cfg->a, basedn).ptr;
174 if(!authdb->config.basedn) return NULL;
173 175
174 // optional config 176 // optional config
175 if(binddn.ptr) { 177 if(binddn.ptr) {
176 if(!bindpw.ptr) { 178 if(!bindpw.ptr) {
177 log_ereport(LOG_FAILURE, "ldap authdb %s: binddn specified, but no bindpw", name); 179 log_ereport(LOG_FAILURE, "ldap authdb %s: binddn specified, but no bindpw", name);
178 return NULL; 180 return NULL;
179 } 181 }
180 182
181 authdb->config.binddn = binddn.ptr; 183 authdb->config.binddn = cx_strdup_a(cfg->a, binddn).ptr;
182 authdb->config.bindpw = bindpw.ptr; 184 authdb->config.bindpw = cx_strdup_a(cfg->a, bindpw).ptr;
183 } 185
186 if(!authdb->config.binddn || !authdb->config.bindpw) {
187 return NULL;
188 }
189 }
190
184 191
185 if(userSearchFilter.ptr) { 192 if(userSearchFilter.ptr) {
186 authdb->config.userSearchFilter = userSearchFilter.ptr; 193 authdb->config.userSearchFilter = cx_strdup_a(cfg->a, userSearchFilter).ptr;
187 } 194 }
188 if(uidAttributes.ptr) { 195 if(uidAttributes.ptr) {
189 authdb->config.numUidAttributes = cx_strsplit_a( 196 cxmutstr uidAttributesCopy = cx_strdup_a(cfg->a, uidAttributes);
190 cfg->a, 197 if(uidAttributesCopy.ptr) {
191 uidAttributes, 198 authdb->config.numUidAttributes = cx_strsplit_a(
192 cx_str(","), 199 cfg->a,
193 1024, 200 cx_strcast(uidAttributesCopy),
194 &authdb->config.uidAttributes); 201 cx_str(","),
202 1024,
203 &authdb->config.uidAttributes);
204 }
195 } 205 }
196 if(groupSearchFilter.ptr) { 206 if(groupSearchFilter.ptr) {
197 authdb->config.groupSearchFilter = groupSearchFilter.ptr; 207 authdb->config.groupSearchFilter = groupSearchFilter.ptr;
198 } 208 }
199 if(memberAttributes.ptr) { 209 if(memberAttributes.ptr) {
200 authdb->config.numMemberAttributes = cx_strsplit_a( 210 cxmutstr memberAttributesCopy = cx_strdup_a(cfg->a, memberAttributes);
201 cfg->a, 211 if(memberAttributesCopy.ptr) {
202 memberAttributes, 212 authdb->config.numMemberAttributes = cx_strsplit_a(
203 cx_str(","), 213 cfg->a,
204 1024, 214 cx_strcast(memberAttributesCopy),
205 &authdb->config.memberAttributes); 215 cx_str(","),
216 1024,
217 &authdb->config.memberAttributes);
218 }
206 } 219 }
207 if(memberType.ptr) { 220 if(memberType.ptr) {
208 if(!cx_strcmp(memberType, cx_str("dn"))) { 221 if(!cx_strcmp(memberType, cx_str("dn"))) {
209 authdb->config.groupMemberType = WS_LDAP_GROUP_MEMBER_DN; 222 authdb->config.groupMemberType = WS_LDAP_GROUP_MEMBER_DN;
210 } else if(cx_strcmp(memberType, cx_str("uid"))) { 223 } else if(!cx_strcmp(memberType, cx_str("uid"))) {
211 authdb->config.groupMemberType = WS_LDAP_GROUP_MEMBER_UID; 224 authdb->config.groupMemberType = WS_LDAP_GROUP_MEMBER_UID;
212 } else { 225 } else {
213 log_ereport(LOG_FAILURE, "ldap authdb %s: unknown MemberType %s", name, memberType.ptr); 226 log_ereport(LOG_FAILURE, "ldap authdb %s: unknown MemberType %s", name, memberType.ptr);
214 return NULL; 227 return NULL;
215 } 228 }
255 } 268 }
256 269
257 return ldap; 270 return ldap;
258 } 271 }
259 272
273 static LDAPUser* ldap_msg_to_user(
274 Session *sn,
275 Request *rq,
276 LDAPAuthDB *authdb,
277 LDAP *ldap,
278 LDAPMessage *msg)
279 {
280 CxAllocator *a = pool_allocator(sn->pool);
281
282 LDAPUser *user = pool_malloc(sn->pool, sizeof(LDAPUser));
283 if(!user) {
284 return NULL;
285 }
286
287 // get dn
288 char *ldap_dn = ldap_get_dn(ldap, msg);
289 if(!ldap_dn) {
290 return NULL;
291 }
292 char *dn = pool_strdup(sn->pool, ldap_dn);
293 ldap_memfree(ldap_dn);
294 if(!dn) {
295 return NULL;
296 }
297
298 // get uid
299 char *uid = NULL;
300
301 // values of configured UidAttributes
302 size_t numUidAttributes = authdb->config.numUidAttributes;
303 cxmutstr *uid_values = pool_calloc(sn->pool, authdb->config.numUidAttributes, sizeof(cxmutstr));
304 if(!uid_values) {
305 return NULL;
306 }
307
308
309 BerElement *ber = NULL;
310 char *attribute = ldap_first_attribute(ldap, msg, &ber);
311 while(attribute) {
312 cxstring attr = cx_str(attribute);
313 for(int i=0;i<numUidAttributes;i++) {
314 // check if the attribute is one of the uid attributes
315 if(!uid_values[i].ptr && !cx_strcmp(attr, authdb->config.uidAttributes[i])) {
316 // copy value to uid_values
317 struct berval **values = ldap_get_values_len(ldap, msg, attribute);
318 if(values) {
319 int count = ldap_count_values_len(values);
320 if(count > 0) {
321 cxstring attr_val = cx_strn(values[0]->bv_val, values[0]->bv_len);
322 uid_values[i] = cx_strdup_a(a, attr_val);
323 } else {
324 log_ereport(LOG_FAILURE, "ldap user: dn: %s attribute %s: no values", dn, attribute);
325 }
326 ldap_value_free_len(values);
327 }
328 }
329 }
330 if(uid_values[0].ptr) {
331 // if we found a value for the first attribute, we can use that
332 break;
333 }
334
335 ldap_memfree(attribute);
336 attribute = ldap_next_attribute(ldap, msg, ber);
337 }
338
339
340 // use first value as uid
341 for(int i=0;i<numUidAttributes;i++) {
342 if(uid_values[i].ptr) {
343 if(!uid) {
344 uid = uid_values[i].ptr;
345 } else {
346 cxFree(a, uid_values[i].ptr);
347 }
348 }
349 }
350 pool_free(sn->pool, uid_values);
351
352 // get user name
353 char *username;
354 if(authdb->config.userNameIsDN) {
355 username = dn;
356 } else {
357 username = uid;
358 }
359
360 if(!username) {
361 return NULL;
362 }
363
364 user->authdb = authdb;
365 user->user.verify_password = ldap_user_verify_password;
366 user->user.check_group = ldap_user_check_group;
367 user->user.free = ldap_user_free;
368 user->user.name = username;
369 user->sn = sn;
370 user->rq = rq;
371
372 // TODO: get uid/gid from ldap
373 user->user.uid = -1;
374 user->user.gid = -1;
375
376 user->ldap = ldap;
377 user->userdn = dn;
378 user->uid_attr = uid;
379
380 return user;
381 }
382
260 User* ldap_get_user(AuthDB *db, Session *sn, Request *rq, const char *username) { 383 User* ldap_get_user(AuthDB *db, Session *sn, Request *rq, const char *username) {
261 LDAPAuthDB *authdb = (LDAPAuthDB*) db; 384 LDAPAuthDB *authdb = (LDAPAuthDB*) db;
262 LDAPConfig *config = &authdb->config; 385 LDAPConfig *config = &authdb->config;
386 CxAllocator *a = pool_allocator(sn->pool);
263 387
264 LDAP *ld = get_ldap_session(sn, rq, authdb); 388 LDAP *ld = get_ldap_session(sn, rq, authdb);
265 if (ld == NULL) { 389 if (ld == NULL) {
266 fprintf(stderr, "ldap_init failed\n");
267 return NULL; 390 return NULL;
268 } 391 }
269 392
270 // get the user dn 393 // get the user dn
271 // TODO: use config for filter 394 cxstring userSearch = cx_str(config->userSearchFilter);
272 // TODO: use asprintf 395 cxmutstr filter = cx_strreplace_a(a, userSearch, cx_str("%s"), cx_str(username));
273 char filter[128]; 396 if(!filter.ptr) {
274 snprintf(filter, 128, "(uid=%s)", username); 397 return NULL;
275 398 }
399
400 log_ereport(LOG_DEBUG, "ldap_get_user: filter: %s", filter.ptr);
401
276 LDAPMessage *result; 402 LDAPMessage *result;
277 struct timeval timeout; 403 struct timeval timeout;
278 timeout.tv_sec = 8; 404 timeout.tv_sec = 8; // TODO: add config parameter for timeout
279 timeout.tv_usec = 0; 405 timeout.tv_usec = 0;
280 int r = ldap_search_ext_s( 406 int r = ldap_search_ext_s(
281 ld, 407 ld,
282 config->basedn, 408 config->basedn,
283 LDAP_SCOPE_SUBTREE, 409 LDAP_SCOPE_SUBTREE,
284 filter, 410 filter.ptr,
285 NULL, 411 NULL,
286 0, 412 0,
287 NULL, // server controls 413 NULL, // server controls
288 NULL, // client controls 414 NULL, // client controls
289 &timeout, 415 &timeout,
290 1, // size limit 416 2, // size limit
291 &result); 417 &result);
292 if (r != LDAP_SUCCESS) { 418 cxFree(a, filter.ptr);
293 //ws_ldap_close(ld); 419 if(r != LDAP_SUCCESS) {
294 420 if(result) {
421 ldap_msgfree(result);
422 }
295 log_ereport(LOG_FAILURE, "ldap_get_user: search failed: %s", ldap_err2string(r)); 423 log_ereport(LOG_FAILURE, "ldap_get_user: search failed: %s", ldap_err2string(r));
296 return NULL; 424 return NULL;
297 } 425 }
426 if(!result) {
427 // not sure if this can happen
428 log_ereport(LOG_FAILURE, "ldap_get_user: search failed: no result");
429 return NULL;
430 }
298 431
299 LDAPMessage *msg = ldap_first_entry(ld, result); 432 LDAPMessage *msg = ldap_first_entry(ld, result);
300 if (msg) { 433 LDAPUser *user = NULL;
301 LDAPUser *user = pool_malloc(sn->pool, sizeof(LDAPUser)); 434 if(msg) {
302 if (user != NULL) { 435 if(ldap_count_entries(ld, msg) > 1) {
303 user->authdb = authdb; 436 log_ereport(LOG_FAILURE, "ldap_get_user: more than one search result");
304 user->user.verify_password = ldap_user_verify_password; 437 } else {
305 user->user.check_group = ldap_user_check_group; 438 user = ldap_msg_to_user(sn, rq, authdb, ld, msg);
306 user->user.free = ldap_user_free; 439 }
307 user->user.name = pool_strdup(sn->pool, username); 440 }
308 user->sn = sn; 441 ldap_msgfree(result);
309 user->rq = rq; 442
310 443 return (User*)user;
311 // TODO: get uid/gid from ldap
312 user->user.uid = -1;
313 user->user.gid = -1;
314
315 user->ldap = ld;
316 user->userdn = ldap_get_dn(ld, msg);
317
318 ldap_msgfree(result);
319
320 return (User*)user;
321 }
322 }
323
324 //ws_ldap_close(ld);
325 return NULL;
326 } 444 }
327 445
328 LDAPGroup* ldap_get_group(Session *sn, Request *rq, LDAPAuthDB *authdb, const char *group) { 446 LDAPGroup* ldap_get_group(Session *sn, Request *rq, LDAPAuthDB *authdb, const char *group) {
329 printf("ldap_get_group: %s\n", group); 447 printf("ldap_get_group: %s\n", group);
330 448
431 &cred, 549 &cred,
432 NULL, 550 NULL,
433 NULL, 551 NULL,
434 &server_cred); 552 &server_cred);
435 if(r == LDAP_SUCCESS) { 553 if(r == LDAP_SUCCESS) {
436 printf("ldap password ok\n"); 554 log_ereport(LOG_VERBOSE, "ldap user %s password ok", user->userdn);
437 return 1; 555 return 1;
438 } else { 556 } else {
439 printf("ldap password not ok\n"); 557 log_ereport(LOG_VERBOSE, "ldap user %s password not ok", user->userdn);
440 return 0; 558 return 0;
441 } 559 }
442 } 560 }
443 561
444 int ldap_user_check_group(User *u, const char *group_str) { 562 int ldap_user_check_group(User *u, const char *group_str) {

mercurial