📄 smbldap.c
字号:
t = SMB_XMALLOC_P(struct smbldap_state_lookup); ZERO_STRUCTP(t); DLIST_ADD_END(smbldap_state_lookup_list, t, tmp); t->ld = ld; t->smbldap_state = smbldap_state;}/******************************************************************** start TLS on an existing LDAP connection*******************************************************************/int smb_ldap_start_tls(LDAP *ldap_struct, int version){ int rc; if (lp_ldap_ssl() != LDAP_SSL_START_TLS) { return LDAP_SUCCESS; } #ifdef LDAP_OPT_X_TLS if (version != LDAP_VERSION3) { DEBUG(0, ("Need LDAPv3 for Start TLS\n")); return LDAP_OPERATIONS_ERROR; } if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) { DEBUG(0,("Failed to issue the StartTLS instruction: %s\n", ldap_err2string(rc))); return rc; } DEBUG (3, ("StartTLS issued: using a TLS connection\n")); return LDAP_SUCCESS;#else DEBUG(0,("StartTLS not supported by LDAP client libraries!\n")); return LDAP_OPERATIONS_ERROR;#endif}/******************************************************************** setup a connection to the LDAP server based on a uri*******************************************************************/int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri){ int rc; DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri)); #ifdef HAVE_LDAP_INITIALIZE rc = ldap_initialize(ldap_struct, uri); if (rc) { DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); } return rc;#else /* Parse the string manually */ { int port = 0; fstring protocol; fstring host; SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); /* skip leading "URL:" (if any) */ if ( strnequal( uri, "URL:", 4 ) ) { uri += 4; } sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port); if (port == 0) { if (strequal(protocol, "ldap")) { port = LDAP_PORT; } else if (strequal(protocol, "ldaps")) { port = LDAPS_PORT; } else { DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); } } if ((*ldap_struct = ldap_init(host, port)) == NULL) { DEBUG(0, ("ldap_init failed !\n")); return LDAP_OPERATIONS_ERROR; } if (strequal(protocol, "ldaps")) {#ifdef LDAP_OPT_X_TLS int tls = LDAP_OPT_X_TLS_HARD; if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) { DEBUG(0, ("Failed to setup a TLS session\n")); } DEBUG(3,("LDAPS option set...!\n"));#else DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n")); return LDAP_OPERATIONS_ERROR;#endif /* LDAP_OPT_X_TLS */ } }#endif /* HAVE_LDAP_INITIALIZE */ return LDAP_SUCCESS;}/******************************************************************** try to upgrade to Version 3 LDAP if not already, in either case return current version *******************************************************************/int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version) { int version; int rc; /* assume the worst */ *new_version = LDAP_VERSION2; rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version); if (rc) { return rc; } if (version == LDAP_VERSION3) { *new_version = LDAP_VERSION3; return LDAP_SUCCESS; } /* try upgrade */ version = LDAP_VERSION3; rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version); if (rc) { return rc; } *new_version = LDAP_VERSION3; return LDAP_SUCCESS;}/******************************************************************* open a connection to the ldap server (just until the bind) ******************************************************************/int smb_ldap_setup_full_conn(LDAP **ldap_struct, const char *uri){ int rc, version; rc = smb_ldap_setup_conn(ldap_struct, uri); if (rc) { return rc; } rc = smb_ldap_upgrade_conn(*ldap_struct, &version); if (rc) { return rc; } rc = smb_ldap_start_tls(*ldap_struct, version); if (rc) { return rc; } return LDAP_SUCCESS;}/******************************************************************* open a connection to the ldap server.******************************************************************/static int smbldap_open_connection (struct smbldap_state *ldap_state){ int rc = LDAP_SUCCESS; int version; LDAP **ldap_struct = &ldap_state->ldap_struct; rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri); if (rc) { return rc; } /* Store the LDAP pointer in a lookup list */ smbldap_store_state(*ldap_struct, ldap_state); /* Upgrade to LDAPv3 if possible */ rc = smb_ldap_upgrade_conn(*ldap_struct, &version); if (rc) { return rc; } /* Start TLS if required */ rc = smb_ldap_start_tls(*ldap_struct, version); if (rc) { return rc; } DEBUG(2, ("smbldap_open_connection: connection opened\n")); return rc;}/******************************************************************* a rebind function for authenticated referrals This version takes a void* that we can shove useful stuff in :-)******************************************************************/#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)#elsestatic int rebindproc_with_state (LDAP * ld, char **whop, char **credp, int *methodp, int freeit, void *arg){ struct smbldap_state *ldap_state = arg; /** @TODO Should we be doing something to check what servers we rebind to? Could we get a referral to a machine that we don't want to give our username and password to? */ if (freeit) { SAFE_FREE(*whop); memset(*credp, '\0', strlen(*credp)); SAFE_FREE(*credp); } else { DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", ldap_state->bind_dn)); *whop = SMB_STRDUP(ldap_state->bind_dn); if (!*whop) { return LDAP_NO_MEMORY; } *credp = SMB_STRDUP(ldap_state->bind_secret); if (!*credp) { SAFE_FREE(*whop); return LDAP_NO_MEMORY; } *methodp = LDAP_AUTH_SIMPLE; } GetTimeOfDay(&ldap_state->last_rebind); return 0;}#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*//******************************************************************* a rebind function for authenticated referrals This version takes a void* that we can shove useful stuff in :-) and actually does the connection.******************************************************************/#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)static int rebindproc_connect_with_state (LDAP *ldap_struct, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *arg){ struct smbldap_state *ldap_state = arg; int rc; int version; DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n", url, ldap_state->bind_dn)); /* call START_TLS again (ldaps:// is handled by the OpenLDAP library * itself) before rebinding to another LDAP server to avoid to expose * our credentials. At least *try* to secure the connection - Guenther */ smb_ldap_upgrade_conn(ldap_struct, &version); smb_ldap_start_tls(ldap_struct, version); /** @TODO Should we be doing something to check what servers we rebind to? Could we get a referral to a machine that we don't want to give our username and password to? */ rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); GetTimeOfDay(&ldap_state->last_rebind); return rc;}#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*//******************************************************************* Add a rebind function for authenticated referrals******************************************************************/#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)#else# if LDAP_SET_REBIND_PROC_ARGS == 2static int rebindproc (LDAP *ldap_struct, char **whop, char **credp, int *method, int freeit ){ struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct); return rebindproc_with_state(ldap_struct, whop, credp, method, freeit, ldap_state); }# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*//******************************************************************* a rebind function for authenticated referrals this also does the connection, but no void*.******************************************************************/#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)# if LDAP_SET_REBIND_PROC_ARGS == 2static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request, ber_int_t msgid){ struct smbldap_state *ldap_state = smbldap_find_state(ld); return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, ldap_state);}# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*//******************************************************************* connect to the ldap server under system privilege.******************************************************************/static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_struct){ int rc; char *ldap_dn; char *ldap_secret; int version; /* get the password */ if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) { DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); return LDAP_INVALID_CREDENTIALS; } ldap_state->bind_dn = ldap_dn; ldap_state->bind_secret = ldap_secret; /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite (OpenLDAP) doesnt' seem to support it */ DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n", ldap_state->uri, ldap_dn));#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)# if LDAP_SET_REBIND_PROC_ARGS == 2 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); # endif# if LDAP_SET_REBIND_PROC_ARGS == 3 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state); # endif#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/# if LDAP_SET_REBIND_PROC_ARGS == 2 ldap_set_rebind_proc(ldap_struct, &rebindproc); # endif# if LDAP_SET_REBIND_PROC_ARGS == 3 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state); # endif#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(ldap_state->num_failures ? 2 : 0, ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n", ldap_state->uri, ldap_dn ? ldap_dn : "(unknown)", ldap_err2string(rc), ld_error ? ld_error : "(unknown)")); SAFE_FREE(ld_error); ldap_state->num_failures++; return rc; } ldap_state->num_failures = 0; ldap_state->paged_results = False; ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version); if (smbldap_has_control(ldap_state, ADS_PAGE_CTL_OID) && version == 3) { ldap_state->paged_results = True; } DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n")); DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n", ldap_state->paged_results ? "does" : "does not")); return rc;}/********************************************************************** Connect to LDAP server (called before every ldap operation)*********************************************************************/static int smbldap_open(struct smbldap_state *ldap_state){ int rc, opt_rc; BOOL reopen = False; SMB_ASSERT(ldap_state); #ifndef NO_LDAP_SECURITY if (geteuid() != 0) { DEBUG(0, ("smbldap_open: cannot access LDAP when not root..\n")); return LDAP_INSUFFICIENT_ACCESS; }#endif if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time(NULL))) { struct sockaddr_un addr; socklen_t len = sizeof(addr); int sd; opt_rc = ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd); if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 ) reopen = True;#ifdef HAVE_UNIXSOCKET if (opt_rc == 0 && addr.sun_family == AF_UNIX) reopen = True;#endif if (reopen) { /* the other end has died. reopen. */ ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); ldap_state->ldap_struct = NULL; ldap_state->last_ping = (time_t)0; } else { ldap_state->last_ping = time(NULL); } } if (ldap_state->ldap_struct != NULL) { DEBUG(11,("smbldap_open: already connected to the LDAP server\n")); return LDAP_SUCCESS; } if ((rc = smbldap_open_connection(ldap_state))) { return rc; } if ((rc = smbldap_connect_system(ldap_state, ldap_state->ldap_struct))) { ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); ldap_state->ldap_struct = NULL; return rc; } ldap_state->last_ping = time(NULL); ldap_state->pid = sys_getpid(); DEBUG(4,("The LDAP server is succesfully connected\n")); return LDAP_SUCCESS;}/**********************************************************************Disconnect from LDAP server *********************************************************************/static NTSTATUS smbldap_close(struct smbldap_state *ldap_state){ if (!ldap_state) return NT_STATUS_INVALID_PARAMETER; if (ldap_state->ldap_struct != NULL) { ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); ldap_state->ldap_struct = NULL; } smbldap_delete_state(ldap_state); DEBUG(5,("The connection to the LDAP server was closed\n")); /* maybe free the results here --metze */ return NT_STATUS_OK;}static BOOL got_alarm;static void (*old_handler)(int);static void gotalarm_sig(int dummy){ got_alarm = True;}static int another_ldap_try(struct smbldap_state *ldap_state, int *rc, int *attempts, time_t endtime){ time_t now = time(NULL); int open_rc = LDAP_SERVER_DOWN; if (*rc != LDAP_SERVER_DOWN) goto no_next; if (now >= endtime) { smbldap_close(ldap_state); *rc = LDAP_TIMEOUT; goto no_next; } if (*attempts == 0) { got_alarm = False; old_handler = CatchSignal(SIGALRM, gotalarm_sig); alarm(endtime - now); if (ldap_state->pid != sys_getpid()) smbldap_close(ldap_state); } while (1) { if (*attempts != 0) smb_msleep(1000);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -