📄 smbldap.c
字号:
*attempts += 1; open_rc = smbldap_open(ldap_state); if (open_rc == LDAP_SUCCESS) { ldap_state->last_use = now; return True; } if (got_alarm) { *rc = LDAP_TIMEOUT; break; } if (open_rc != LDAP_SUCCESS) { DEBUG(1, ("Connection to LDAP server failed for the " "%d try!\n", *attempts)); } } no_next: CatchSignal(SIGALRM, old_handler); alarm(0); ldap_state->last_use = now; return False;}/********************************************************************* ********************************************************************/static int smbldap_search_ext(struct smbldap_state *ldap_state, const char *base, int scope, const char *filter, const char *attrs[], int attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, int sizelimit, LDAPMessage **res){ int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_filter; time_t endtime = time(NULL)+lp_ldap_timeout(); struct timeval timeout; SMB_ASSERT(ldap_state); DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], " "scope => [%d]\n", base, filter, scope)); if (ldap_state->last_rebind.tv_sec > 0) { struct timeval tval; SMB_BIG_INT tdiff = 0; int sleep_time = 0; ZERO_STRUCT(tval); GetTimeOfDay(&tval); tdiff = usec_time_diff(&tval, &ldap_state->last_rebind); tdiff /= 1000; /* Convert to milliseconds. */ sleep_time = lp_ldap_replication_sleep()-(int)tdiff; sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME); if (sleep_time > 0) { /* we wait for the LDAP replication */ DEBUG(5,("smbldap_search_ext: waiting %d milliseconds " "for LDAP replication.\n",sleep_time)); smb_msleep(sleep_time); DEBUG(5,("smbldap_search_ext: go on!\n")); } ZERO_STRUCT(ldap_state->last_rebind); } if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) { return LDAP_NO_MEMORY; } /* Setup timeout for the ldap_search_ext_s call - local and remote. */ timeout.tv_sec = lp_ldap_timeout(); timeout.tv_usec = 0; /* Setup alarm timeout.... Do we need both of these ? JRA. * Yes, I think we do need both of these. The server timeout only * covers the case where the server's operation takes too long. It * does not cover the case where the request hangs on its way to the * server. The server side timeout is not strictly necessary, it's * just a bit more kind to the server. VL. */ got_alarm = 0; CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); alarm(lp_ldap_timeout()); /* End setup timeout. */ while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope, utf8_filter, CONST_DISCARD(char **, attrs), attrsonly, sctrls, cctrls, &timeout, sizelimit, res); SAFE_FREE(utf8_filter); /* Teardown timeout. */ CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); alarm(0); if (got_alarm != 0) return LDAP_TIMELIMIT_EXCEEDED; return rc;}int smbldap_search(struct smbldap_state *ldap_state, const char *base, int scope, const char *filter, const char *attrs[], int attrsonly, LDAPMessage **res){ return smbldap_search_ext(ldap_state, base, scope, filter, attrs, attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);}int smbldap_search_paged(struct smbldap_state *ldap_state, const char *base, int scope, const char *filter, const char **attrs, int attrsonly, int pagesize, LDAPMessage **res, void **cookie){ LDAPControl pr; LDAPControl **rcontrols; LDAPControl *controls[2] = { NULL, NULL}; BerElement *cookie_be = NULL; struct berval *cookie_bv = NULL; int tmp = 0, i, rc; BOOL critical = True; *res = NULL; DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s]," "scope => [%d], pagesize => [%d]\n", base, filter, scope, pagesize)); cookie_be = ber_alloc_t(LBER_USE_DER); if (cookie_be == NULL) { DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns " "NULL\n")); return LDAP_NO_MEMORY; } /* construct cookie */ if (*cookie != NULL) { ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie); ber_bvfree(*cookie); /* don't need it from last time */ *cookie = NULL; } else { ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0); } ber_flatten(cookie_be, &cookie_bv); pr.ldctl_oid = CONST_DISCARD(char *, ADS_PAGE_CTL_OID); pr.ldctl_iscritical = (char) critical; pr.ldctl_value.bv_len = cookie_bv->bv_len; pr.ldctl_value.bv_val = cookie_bv->bv_val; controls[0] = ≺ controls[1] = NULL; rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs, 0, controls, NULL, LDAP_NO_LIMIT, res); ber_free(cookie_be, 1); ber_bvfree(cookie_bv); if (rc != 0) { DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) " "failed with [%s]\n", filter, ldap_err2string(rc))); goto done; } DEBUG(3,("smbldap_search_paged: search was successfull\n")); rc = ldap_parse_result(ldap_state->ldap_struct, *res, NULL, NULL, NULL, NULL, &rcontrols, 0); if (rc != 0) { DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \ "with [%s]\n", ldap_err2string(rc))); goto done; } if (rcontrols == NULL) goto done; for (i=0; rcontrols[i]; i++) { if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0) continue; cookie_be = ber_init(&rcontrols[i]->ldctl_value); ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv); /* the berval is the cookie, but must be freed when it is all done */ if (cookie_bv->bv_len) *cookie=ber_bvdup(cookie_bv); else *cookie=NULL; ber_bvfree(cookie_bv); ber_free(cookie_be, 1); break; } ldap_controls_free(rcontrols);done: return rc;}int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[]){ int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; time_t endtime = time(NULL)+lp_ldap_timeout(); SMB_ASSERT(ldap_state); DEBUG(5,("smbldap_modify: dn => [%s]\n", dn )); if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { return LDAP_NO_MEMORY; } while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs); SAFE_FREE(utf8_dn); return rc;}int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[]){ int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; time_t endtime = time(NULL)+lp_ldap_timeout(); SMB_ASSERT(ldap_state); DEBUG(5,("smbldap_add: dn => [%s]\n", dn )); if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { return LDAP_NO_MEMORY; } while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs); SAFE_FREE(utf8_dn); return rc;}int smbldap_delete(struct smbldap_state *ldap_state, const char *dn){ int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; time_t endtime = time(NULL)+lp_ldap_timeout(); SMB_ASSERT(ldap_state); DEBUG(5,("smbldap_delete: dn => [%s]\n", dn )); if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { return LDAP_NO_MEMORY; } while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn); SAFE_FREE(utf8_dn); return rc;}int smbldap_extended_operation(struct smbldap_state *ldap_state, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap){ int rc = LDAP_SERVER_DOWN; int attempts = 0; time_t endtime = time(NULL)+lp_ldap_timeout(); if (!ldap_state) return (-1); while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap); return rc;}/******************************************************************* run the search by name.******************************************************************/int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter, const char **search_attr, LDAPMessage ** result){ int scope = LDAP_SCOPE_SUBTREE; int rc; rc = smbldap_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0,("smbldap_search_suffix: Problem during the LDAP search: %s (%s)\n", ld_error?ld_error:"(unknown)", ldap_err2string (rc))); SAFE_FREE(ld_error); } return rc;}static void smbldap_idle_fn(void **data, time_t *interval, time_t now){ struct smbldap_state *state = (struct smbldap_state *)(*data); if (state->ldap_struct == NULL) { DEBUG(10,("ldap connection not connected...\n")); return; } if ((state->last_use+SMBLDAP_IDLE_TIME) > now) { DEBUG(10,("ldap connection not idle...\n")); return; } DEBUG(7,("ldap connection idle...closing connection\n")); smbldap_close(state);}/********************************************************************** Housekeeping *********************************************************************/void smbldap_free_struct(struct smbldap_state **ldap_state) { smbldap_close(*ldap_state); if ((*ldap_state)->bind_secret) { memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret)); } SAFE_FREE((*ldap_state)->bind_dn); SAFE_FREE((*ldap_state)->bind_secret); smb_unregister_idle_event((*ldap_state)->event_id); *ldap_state = NULL; /* No need to free any further, as it is talloc()ed */}/********************************************************************** Intitalise the 'general' ldap structures, on which ldap operations may be conducted *********************************************************************/NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_state **smbldap_state) { *smbldap_state = TALLOC_ZERO_P(mem_ctx, struct smbldap_state); if (!*smbldap_state) { DEBUG(0, ("talloc() failed for ldapsam private_data!\n")); return NT_STATUS_NO_MEMORY; } if (location) { (*smbldap_state)->uri = talloc_strdup(mem_ctx, location); } else { (*smbldap_state)->uri = "ldap://localhost"; } (*smbldap_state)->event_id = smb_register_idle_event(smbldap_idle_fn, (void *)(*smbldap_state), SMBLDAP_IDLE_TIME); if ((*smbldap_state)->event_id == SMB_EVENT_ID_INVALID) { DEBUG(0,("Failed to register LDAP idle event!\n")); return NT_STATUS_INVALID_HANDLE; } return NT_STATUS_OK;}/******************************************************************* Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX.********************************************************************/char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry){ char *utf8_dn, *unix_dn; utf8_dn = ldap_get_dn(ld, entry); if (!utf8_dn) { DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n")); return NULL; } if (pull_utf8_allocate(&unix_dn, utf8_dn) == (size_t)-1) { DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 [%s]\n", utf8_dn)); return NULL; } ldap_memfree(utf8_dn); return unix_dn;}/******************************************************************* Check if root-dse has a certain Control or Extension********************************************************************/static BOOL smbldap_check_root_dse(struct smbldap_state *ldap_state, const char **attrs, const char *value) { LDAPMessage *msg = NULL; LDAPMessage *entry = NULL; char **values = NULL; int rc, num_result, num_values, i; BOOL result = False; if (!attrs[0]) { DEBUG(3,("smbldap_check_root_dse: nothing to look for\n")); return False; } if (!strequal(attrs[0], "supportedExtension") && !strequal(attrs[0], "supportedControl") && !strequal(attrs[0], "namingContexts")) { DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0])); return False; } rc = ldap_search_s(ldap_state->ldap_struct, "", LDAP_SCOPE_BASE, "(objectclass=*)", CONST_DISCARD(char **, attrs), 0 , &msg); if (rc != LDAP_SUCCESS) { DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n")); return False; } num_result = ldap_count_entries(ldap_state->ldap_struct, msg); if (num_result != 1) { DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result)); goto done; } entry = ldap_first_entry(ldap_state->ldap_struct, msg); if (entry == NULL) { DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n")); goto done; } values = ldap_get_values(ldap_state->ldap_struct, entry, attrs[0]); if (values == NULL) { DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0])); goto done; } num_values = ldap_count_values(values); if (num_values == 0) { DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0])); goto done; } for (i=0; i<num_values; i++) { if (strcmp(values[i], value) == 0) result = True; } done: if (values != NULL) ldap_value_free(values); if (msg != NULL) ldap_msgfree(msg); return result;}/******************************************************************* Check if LDAP-Server supports a certain Control (OID in string format)********************************************************************/BOOL smbldap_has_control(struct smbldap_state *ldap_state, const char *control){ const char *attrs[] = { "supportedControl", NULL }; return smbldap_check_root_dse(ldap_state, attrs, control);}/******************************************************************* Check if LDAP-Server supports a certain Extension (OID in string format)********************************************************************/BOOL smbldap_has_extension(struct smbldap_state *ldap_state, const char *extension){ const char *attrs[] = { "supportedExtension", NULL }; return smbldap_check_root_dse(ldap_state, attrs, extension);}/******************************************************************* Check if LDAP-Server holds a given namingContext********************************************************************/BOOL smbldap_has_naming_context(struct smbldap_state *ldap_state, const char *naming_context){ const char *attrs[] = { "namingContexts", NULL }; return smbldap_check_root_dse(ldap_state, attrs, naming_context);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -