int slapi_apib_release(void **api) { APIB_FEATURES *features; int ret; slapi_lock_mutex(((APIB_FEATURES*)(api[0]))->lock); ret = --(((APIB_FEATURES*)(api[0]))->refcount); if(((APIB_FEATURES*)(api[0]))->refcount == 0 && ((APIB_FEATURES*)(api[0]))->callback_on_zero) { /* save our stuff for when it gets zapped */ features = (APIB_FEATURES*)api[0]; if(0==((APIB_FEATURES*)(api[0]))->callback_on_zero(api)) /* this should deregister the interface */ { slapi_unlock_mutex(features->lock); slapi_destroy_mutex(features->lock); slapi_ch_free((void **)&features); } else slapi_unlock_mutex(features->lock); } else slapi_unlock_mutex(((APIB_FEATURES*)(api[0]))->lock); return ret; }
int slapi_apib_get_interface(char *guid, void ***api) { int ret = -1; ABAPI **theapi; if(buffer_lock == 0) return ret; if(buffer_lock == 0) { if(0 == (buffer_lock = slapi_new_mutex())) /* we never free this mutex */ /* badness */ return -1; } slapi_lock_mutex(buffer_lock); if((theapi = ABAPIBroker_FindInterface(guid)) != NULL) { *api = (*theapi)->api; if((*api)[0]) { slapi_apib_addref(*api); } ret = 0; } slapi_unlock_mutex(buffer_lock); return ret; }
int slapi_apib_get_interface_all(char *guid, void ****api) { void ***retapi = NULL; int idx = 0; if(buffer_lock == 0) return -1; if(buffer_lock == 0) { if(0 == (buffer_lock = slapi_new_mutex())) /* we never free this mutex */ /* badness */ return -1; } slapi_lock_mutex(buffer_lock); retapi = ABAPIBroker_FindInterface_All(guid); for (idx = 0; retapi && retapi[idx]; ++idx) { void **theapi = retapi[idx]; if(theapi[0]) { slapi_apib_addref(theapi); } } *api = retapi; slapi_unlock_mutex(buffer_lock); return 0; }
void set_snmp_interaction_row(char *host, int port, int error) { int index; int isnew = 0; char *dsName; char *dsURL; /* stevross: our servers don't have a concept of dsName as a distinguished name as specified in the MIB. Make this "Not Available" for now waiting for sometime in the future when we do */ dsName = "Not Available"; dsURL= make_ds_url(host, port); /* lock around here to avoid race condition of two threads trying to update table at same time */ slapi_lock_mutex(interaction_table_mutex); index = search_interaction_table(dsURL, &isnew); if(isnew){ /* fillin the new row from scratch*/ g_get_global_snmp_vars()->int_tbl[index].dsIntIndex = index; strncpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName, sizeof(g_get_global_snmp_vars()->int_tbl[index].dsName)); g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation = time(0); g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0); if(error == 0){ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0); g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0; g_get_global_snmp_vars()->int_tbl[index].dsFailures = 0; g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 1; } else { g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = 0; g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 1; g_get_global_snmp_vars()->int_tbl[index].dsFailures = 1; g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 0; } strncpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL, sizeof(g_get_global_snmp_vars()->int_tbl[index].dsURL)); } else { /* just update the appropriate fields */ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0); if(error == 0){ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0); g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0; g_get_global_snmp_vars()->int_tbl[index].dsSuccesses += 1; }else{ g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess +=1; g_get_global_snmp_vars()->int_tbl[index].dsFailures +=1; } } slapi_unlock_mutex(interaction_table_mutex); /* free the memory allocated for dsURL in call to ds_make_url */ if(dsURL != NULL){ slapi_ch_free( (void**)&dsURL ); } }
void cb_update_failed_conn_cpt ( cb_backend_instance *cb ) { /* if the chaining BE is already unavailable, we do nothing*/ time_t now; if (cb->monitor_availability.farmserver_state == FARMSERVER_AVAILABLE) { slapi_lock_mutex(cb->monitor_availability.cpt_lock); cb->monitor_availability.cpt ++; slapi_unlock_mutex(cb->monitor_availability.cpt_lock); if (cb->monitor_availability.cpt >= CB_NUM_CONN_BEFORE_UNAVAILABILITY ) { /* we reach the limit of authorized failed connections => we setup the chaining BE state to unavailable */ now = current_time(); slapi_lock_mutex(cb->monitor_availability.lock_timeLimit); cb->monitor_availability.unavailableTimeLimit = now + CB_UNAVAILABLE_PERIOD ; slapi_unlock_mutex(cb->monitor_availability.lock_timeLimit); cb->monitor_availability.farmserver_state = FARMSERVER_UNAVAILABLE ; slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_update_failed_conn_cpt - Farm server unavailable"); } } }
int slapi_apib_addref(void **api) { int ret; slapi_lock_mutex(((APIB_FEATURES*)(api[0]))->lock); ret = ++(((APIB_FEATURES*)(api[0]))->refcount); slapi_unlock_mutex(((APIB_FEATURES*)(api[0]))->lock); return ret; }
void cb_reset_conn_cpt( cb_backend_instance *cb ) { if (cb->monitor_availability.cpt > 0) { slapi_lock_mutex(cb->monitor_availability.cpt_lock); cb->monitor_availability.cpt = 0 ; if (cb->monitor_availability.farmserver_state == FARMSERVER_UNAVAILABLE) { cb->monitor_availability.farmserver_state = FARMSERVER_AVAILABLE ; slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_reset_conn_cpt - Farm server is back"); } slapi_unlock_mutex(cb->monitor_availability.cpt_lock); } }
void cb_close_all_connections( Slapi_Backend * be ) { cb_outgoing_conn *conn, *next_conn; cb_backend_instance * cb= cb_get_instance(be); int i; slapi_lock_mutex(cb->pool->conn.conn_list_mutex); if (cb->pool->secure) { for (i=0; i< MAX_CONN_ARRAY; i++) { for (conn = cb->pool->connarray[i]; conn != NULL; conn = next_conn ){ next_conn = conn->next; cb_close_and_dispose_connection(conn); } } } else { for ( conn = cb->pool->conn.conn_list; conn != NULL; conn = next_conn ) { next_conn=conn->next; cb_close_and_dispose_connection(conn); } } slapi_unlock_mutex(cb->pool->conn.conn_list_mutex); slapi_lock_mutex(cb->bind_pool->conn.conn_list_mutex); if (cb->bind_pool->secure) { for (i=0; i< MAX_CONN_ARRAY; i++) { for (conn = cb->bind_pool->connarray[i]; conn != NULL; conn = next_conn ){ next_conn=conn->next; cb_close_and_dispose_connection(conn); } } } else { for ( conn = cb->bind_pool->conn.conn_list; conn != NULL; conn = next_conn ) { next_conn=conn->next; cb_close_and_dispose_connection(conn); } } slapi_unlock_mutex(cb->bind_pool->conn.conn_list_mutex); }
int cb_check_availability( cb_backend_instance *cb, Slapi_PBlock *pb ) { /* check wether the farmserver is available or not */ time_t now ; if ( cb->monitor_availability.farmserver_state == FARMSERVER_UNAVAILABLE ){ slapi_lock_mutex(cb->monitor_availability.lock_timeLimit); now = current_time(); if (now >= cb->monitor_availability.unavailableTimeLimit) { cb->monitor_availability.unavailableTimeLimit = now + CB_INFINITE_TIME ; /* to be sure only one thread can do the test */ slapi_unlock_mutex(cb->monitor_availability.lock_timeLimit); } else { slapi_unlock_mutex(cb->monitor_availability.lock_timeLimit); cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, "FARM SERVER TEMPORARY UNAVAILABLE", 0, NULL) ; return FARMSERVER_UNAVAILABLE ; } slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_check_availability - ping the farm server and check if it's still unavailable"); if (cb_ping_farm(cb, NULL, 0) != LDAP_SUCCESS) { /* farm still unavailable... Just change the timelimit */ slapi_lock_mutex(cb->monitor_availability.lock_timeLimit); now = current_time(); cb->monitor_availability.unavailableTimeLimit = now + CB_UNAVAILABLE_PERIOD ; slapi_unlock_mutex(cb->monitor_availability.lock_timeLimit); cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, "FARM SERVER TEMPORARY UNAVAILABLE", 0, NULL) ; slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_check_availability - Farm server still unavailable"); return FARMSERVER_UNAVAILABLE ; } else { /* farm is back !*/ slapi_lock_mutex(cb->monitor_availability.lock_timeLimit); now = current_time(); cb->monitor_availability.unavailableTimeLimit = now ; /* the unavailable period is finished */ slapi_unlock_mutex(cb->monitor_availability.lock_timeLimit); /* The farmer server state backs to FARMSERVER_AVAILABLE, but this already done in cb_ping_farm, and also the reset of cpt*/ return FARMSERVER_AVAILABLE ; } } return FARMSERVER_AVAILABLE ; }
int slapi_apib_register(char *guid, void **api ) { int ret = -1; ABAPI *item; if(buffer_lock == 0) { if(0 == (buffer_lock = slapi_new_mutex())) /* we never free this mutex */ /* badness */ return -1; } /* simple - we don't check for duplicates */ item = (ABAPI*)slapi_ch_malloc(sizeof(ABAPI)); if(item) { item->guid = guid; item->api = api; slapi_lock_mutex(buffer_lock); if(head == NULL) { head = item; head->next = head; head->prev = head; } else { item->next = head; item->prev = head->prev; head->prev = item; item->prev->next = item; } slapi_unlock_mutex(buffer_lock); ret = 0; } return ret; }
int slapi_apib_unregister(char *guid) { int ret = -1; ABAPI **api; if(buffer_lock == 0) return ret; if(buffer_lock == 0) { if(0 == (buffer_lock = slapi_new_mutex())) /* we never free this mutex */ /* badness */ return -1; } slapi_lock_mutex(buffer_lock); if((api = ABAPIBroker_FindInterface(guid)) != NULL) { (*api)->prev->next = (*api)->next; (*api)->next->prev = (*api)->prev; if(*api == head) { head = (*api)->next; } if(*api == head) /* must be the last item, turn off the lights */ head = 0; slapi_ch_free((void**)api); *api = 0; ret = 0; } slapi_unlock_mutex(buffer_lock); return ret; }
void cb_close_conn_pool(cb_conn_pool * pool) { cb_outgoing_conn *conn, *nextconn; int secure = pool->secure; int i = 0; slapi_lock_mutex( pool->conn.conn_list_mutex ); if (secure) { for (i=0; i< MAX_CONN_ARRAY; i++) { for (conn = pool->connarray[i]; conn != NULL; conn = nextconn) { if ( conn->status != CB_CONNSTATUS_OK ) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_close_conn_pool - Unexpected connection state (%d)\n",conn->status); } nextconn=conn->next; cb_close_and_dispose_connection(conn); } } } else { for ( conn = pool->conn.conn_list; conn != NULL; conn = nextconn ) { if ( conn->status != CB_CONNSTATUS_OK ) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_close_conn_pool - Unexpected connection state (%d)\n",conn->status); } nextconn=conn->next; cb_close_and_dispose_connection(conn); } } pool->conn.conn_list=NULL; pool->conn.conn_list_count=0; slapi_unlock_mutex( pool->conn.conn_list_mutex ); }
/* * Do the actual work of authenticating with PAM. First, get the PAM identity * based on the method used to convert the BIND identity to the PAM identity. * Set up the structures that pam_start needs and call pam_start(). After * that, call pam_authenticate and pam_acct_mgmt. Check the various return * values from these functions and map them to their corresponding LDAP BIND * return values. Return the appropriate LDAP error code. * This function will also set the appropriate LDAP response controls in * the given pblock. * Since this function can be called multiple times, we only want to return * the errors and controls to the user if this is the final call, so the * final_method parameter tells us if this is the last one. Coupled with * the fallback argument, we can tell if we are able to send the response * back to the client. */ static int do_one_pam_auth( Slapi_PBlock *pb, int method, /* get pam identity from ENTRY, RDN, or DN */ PRBool final_method, /* which method is the last one to try */ char *pam_service, /* name of service for pam_start() */ char *map_ident_attr, /* for ENTRY method, name of attribute holding pam identity */ PRBool fallback, /* if true, failure here should fallback to regular bind */ int pw_response_requested /* do we need to send pwd policy resp control */ ) { MyStrBuf pam_id; const char *binddn = NULL; Slapi_DN *bindsdn = NULL; int rc; int retcode = LDAP_SUCCESS; pam_handle_t *pam_handle; struct my_pam_conv_str my_data; struct pam_conv my_pam_conv = {pam_conv_func, NULL}; char *errmsg = NULL; /* free with PR_smprintf_free */ int locked = 0; slapi_pblock_get( pb, SLAPI_BIND_TARGET_SDN, &bindsdn ); if (NULL == bindsdn) { errmsg = PR_smprintf("Null bind dn"); retcode = LDAP_OPERATIONS_ERROR; pam_id.str = NULL; /* initialize pam_id.str */ goto done; /* skip the pam stuff */ } binddn = slapi_sdn_get_dn(bindsdn); if (method == PAMPT_MAP_METHOD_RDN) { derive_from_bind_dn(pb, bindsdn, &pam_id); } else if (method == PAMPT_MAP_METHOD_ENTRY) { derive_from_bind_entry(pb, bindsdn, &pam_id, map_ident_attr, &locked); } else { init_my_str_buf(&pam_id, binddn); } if (locked) { errmsg = PR_smprintf("Account inactivated. Contact system administrator."); retcode = LDAP_UNWILLING_TO_PERFORM; /* user inactivated */ goto done; /* skip the pam stuff */ } if (!pam_id.str) { errmsg = PR_smprintf("Bind DN [%s] is invalid or not found", binddn); retcode = LDAP_NO_SUCH_OBJECT; /* user unknown */ goto done; /* skip the pam stuff */ } /* do the pam stuff */ my_data.pb = pb; my_data.pam_identity = pam_id.str; my_pam_conv.appdata_ptr = &my_data; slapi_lock_mutex(PAMLock); /* from this point on we are in the critical section */ rc = pam_start(pam_service, pam_id.str, &my_pam_conv, &pam_handle); report_pam_error("during pam_start", rc, pam_handle); if (rc == PAM_SUCCESS) { /* use PAM_SILENT - there is no user interaction at this point */ rc = pam_authenticate(pam_handle, 0); report_pam_error("during pam_authenticate", rc, pam_handle); /* check different types of errors here */ if (rc == PAM_USER_UNKNOWN) { errmsg = PR_smprintf("User id [%s] for bind DN [%s] does not exist in PAM", pam_id.str, binddn); retcode = LDAP_NO_SUCH_OBJECT; /* user unknown */ } else if (rc == PAM_AUTH_ERR) { errmsg = PR_smprintf("Invalid PAM password for user id [%s], bind DN [%s]", pam_id.str, binddn); retcode = LDAP_INVALID_CREDENTIALS; /* invalid creds */ } else if (rc == PAM_MAXTRIES) { errmsg = PR_smprintf("Authentication retry limit exceeded in PAM for " "user id [%s], bind DN [%s]", pam_id.str, binddn); if (pw_response_requested) { slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_ACCTLOCKED); } retcode = LDAP_CONSTRAINT_VIOLATION; /* max retries */ } else if (rc != PAM_SUCCESS) { errmsg = PR_smprintf("Unknown PAM error [%s] for user id [%s], bind DN [%s]", pam_strerror(pam_handle, rc), pam_id.str, binddn); retcode = LDAP_OPERATIONS_ERROR; /* pam config or network problem */ } } /* if user authenticated successfully, see if there is anything we need to report back w.r.t. password or account lockout */ if (rc == PAM_SUCCESS) { rc = pam_acct_mgmt(pam_handle, 0); report_pam_error("during pam_acct_mgmt", rc, pam_handle); /* check different types of errors here */ if (rc == PAM_USER_UNKNOWN) { errmsg = PR_smprintf("User id [%s] for bind DN [%s] does not exist in PAM", pam_id.str, binddn); retcode = LDAP_NO_SUCH_OBJECT; /* user unknown */ } else if (rc == PAM_AUTH_ERR) { errmsg = PR_smprintf("Invalid PAM password for user id [%s], bind DN [%s]", pam_id.str, binddn); retcode = LDAP_INVALID_CREDENTIALS; /* invalid creds */ } else if (rc == PAM_PERM_DENIED) { errmsg = PR_smprintf("Access denied for PAM user id [%s], bind DN [%s]" " - see administrator", pam_id.str, binddn); if (pw_response_requested) { slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_ACCTLOCKED); } retcode = LDAP_UNWILLING_TO_PERFORM; } else if (rc == PAM_ACCT_EXPIRED) { errmsg = PR_smprintf("Expired PAM password for user id [%s], bind DN [%s]: " "reset required", pam_id.str, binddn); slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0); if (pw_response_requested) { slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_PWDEXPIRED); } retcode = LDAP_INVALID_CREDENTIALS; } else if (rc == PAM_NEW_AUTHTOK_REQD) { /* handled same way as ACCT_EXPIRED */ errmsg = PR_smprintf("Expired PAM password for user id [%s], bind DN [%s]: " "reset required", pam_id.str, binddn); slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0); if (pw_response_requested) { slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_PWDEXPIRED); } retcode = LDAP_INVALID_CREDENTIALS; } else if (rc != PAM_SUCCESS) { errmsg = PR_smprintf("Unknown PAM error [%s] for user id [%s], bind DN [%s]", pam_strerror(pam_handle, rc), pam_id.str, binddn); retcode = LDAP_OPERATIONS_ERROR; /* unknown */ } } rc = pam_end(pam_handle, rc); report_pam_error("during pam_end", rc, pam_handle); slapi_unlock_mutex(PAMLock); /* not in critical section any more */ done: delete_my_str_buf(&pam_id); if ((retcode == LDAP_SUCCESS) && (rc != PAM_SUCCESS)) { errmsg = PR_smprintf("Unknown PAM error [%d] for user id [%s], bind DN [%s]", rc, pam_id.str, binddn); retcode = LDAP_OPERATIONS_ERROR; } if (retcode != LDAP_SUCCESS) { slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "%s\n", errmsg); if (final_method && !fallback) { slapi_send_ldap_result(pb, retcode, NULL, errmsg, 0, NULL); } } if (errmsg) { PR_smprintf_free(errmsg); } return retcode; }
int cb_get_connection(cb_conn_pool * pool, LDAP ** lld, cb_outgoing_conn ** cc, struct timeval * maxtime, char **errmsg) { int rc=LDAP_SUCCESS; /* optimistic */ cb_outgoing_conn *conn=NULL; cb_outgoing_conn *connprev=NULL; LDAP *ld=NULL; time_t endbefore=0; int checktime=0; struct timeval bind_to, op_to; unsigned int maxconcurrency,maxconnections; char *password,*binddn,*hostname; unsigned int port; int secure; char *mech = NULL;; static char *error1="Can't contact remote server : %s"; int isMultiThread = ENABLE_MULTITHREAD_PER_CONN ; /* by default, we enable multiple operations per connection */ /* ** return an error if we can't get a connection ** before the operation timeout has expired ** bind_timeout: timeout for the bind operation (if bind needed) ** ( checked in ldap_result ) ** op_timeout: timeout for the op that needs a connection ** ( checked in the loop ) */ *cc=NULL; slapi_rwlock_rdlock(pool->rwl_config_lock); maxconcurrency=pool->conn.maxconcurrency; maxconnections=pool->conn.maxconnections; bind_to.tv_sec = pool->conn.bind_timeout.tv_sec; bind_to.tv_usec = pool->conn.bind_timeout.tv_usec; op_to.tv_sec = pool->conn.op_timeout.tv_sec; op_to.tv_usec = pool->conn.op_timeout.tv_usec; /* SD 02/10/2000 temp fix */ /* allow dynamic update of the binddn & password */ /* host, port and security mode */ /* previous values are NOT freed when changed */ /* won't likely to be changed often */ /* pointers put in the waste basket fields and */ /* freed when the backend is stopped. */ password=pool->password; binddn=pool->binddn; hostname=pool->hostname; port=pool->port; secure=pool->secure; if (pool->starttls) { secure = 2; } mech=pool->mech; slapi_rwlock_unlock(pool->rwl_config_lock); if (secure) { isMultiThread = DISABLE_MULTITHREAD_PER_CONN ; } /* For stupid admins */ if (maxconnections <=0) { static int warned_maxconn = 0; if (!warned_maxconn) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Error (no connection available)\n"); warned_maxconn = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } return LDAP_CONNECT_ERROR; } if (maxtime) { if (maxtime->tv_sec != 0) { checktime=1; endbefore = current_time() + maxtime->tv_sec; /* make sure bind to <= operation timeout */ if ((bind_to.tv_sec==0) || (bind_to.tv_sec > maxtime->tv_sec)) bind_to.tv_sec=maxtime->tv_sec; } } else { if (op_to.tv_sec != 0) { checktime=1; endbefore = current_time() + op_to.tv_sec; /* make sure bind to <= operation timeout */ if ((bind_to.tv_sec==0) || (bind_to.tv_sec > op_to.tv_sec)) bind_to.tv_sec=op_to.tv_sec; } } /* * Close (or mark to be closed) any connections for this farm server that have * exceeded the maximum connection lifetime. */ cb_check_for_stale_connections(pool); /* * Look for an available, already open connection */ slapi_lock_mutex( pool->conn.conn_list_mutex ); if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - server %s conns: %d maxconns: %d\n", hostname, pool->conn.conn_list_count, maxconnections ); } for (;;) { /* time limit mgmt */ if (checktime) { if (current_time() > endbefore ) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - server %s expired.\n", hostname ); if ( errmsg ) { *errmsg = PR_smprintf(error1,"timelimit exceeded"); } rc=LDAP_TIMELIMIT_EXCEEDED; conn=NULL; ld=NULL; goto unlock_and_return; } } /* * First, look for an available, already open/bound connection */ if (secure) { for (conn = pool->connarray[PR_ThreadSelf()]; conn != NULL; conn = conn->next) { if ((conn->ThreadId == PR_MyThreadId()) && (conn->status == CB_CONNSTATUS_OK && conn->refcount < maxconcurrency)){ if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - server found conn 0x%p to use)\n", conn ); } goto unlock_and_return; /* found one */ } } } else { connprev = NULL; for ( conn = pool->conn.conn_list; conn != NULL; conn = conn->next ) { if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - conn 0x%p status %d refcount %lu\n", conn, conn->status, conn->refcount ); } if ( conn->status == CB_CONNSTATUS_OK && conn->refcount < maxconcurrency ) { if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - server found conn 0x%p to use)\n", conn ); } goto unlock_and_return; /* found one */ } connprev = conn; } } if ( secure || pool->conn.conn_list_count <maxconnections) { int version=LDAP_VERSION3; /* * we have not exceeded the maximum number of connections allowed, * so we initialize a new one and add it to the end of our list. */ /* No need to lock. url can't be changed dynamically */ ld = slapi_ldap_init(hostname, port, secure, isMultiThread); if (NULL == ld) { static int warned_init = 0; if (!warned_init) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Can't contact server <%s> port <%d>.\n", hostname, port ); warned_init = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } rc = LDAP_CONNECT_ERROR; goto unlock_and_return; } ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); /* Don't chase referrals */ ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); /* no controls and simple bind only */ /* For now, bind even if no user to detect error */ /* earlier */ if (pool->bindit) { PRErrorCode prerr = 0; LDAPControl **serverctrls=NULL; char *plain = NULL; int ret = -1; rc=LDAP_SUCCESS; if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Bind to to server <%s> port <%d> as <%s>\n", hostname, port, binddn); } ret = pw_rever_decode(password, &plain, CB_CONFIG_USERPASSWORD); /* Pb occured in decryption: stop now, binding will fail */ if ( ret == -1 ) { static int warned_pw = 0; if (!warned_pw) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Internal credentials decoding error; " "password storage schemes do not match or " "encrypted password is corrupted.\n"); warned_pw = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } rc = LDAP_INVALID_CREDENTIALS; goto unlock_and_return; } /* Password-based client authentication */ rc = slapi_ldap_bind(ld, binddn, plain, mech, NULL, &serverctrls, &bind_to, NULL); if ( ret == 0 ) slapi_ch_free_string(&plain); /* free plain only if it has been duplicated */ if ( rc == LDAP_TIMEOUT ) { static int warned_bind_timeout = 0; if (!warned_bind_timeout) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Can't bind to server <%s> port <%d>. (%s)\n", hostname, port, "time-out expired"); warned_bind_timeout = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } rc = LDAP_CONNECT_ERROR; goto unlock_and_return; } else if ( rc != LDAP_SUCCESS ) { prerr=PR_GetError(); static int warned_bind_err = 0; if (!warned_bind_err) { slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Can't bind to server <%s> port <%d>. " "(LDAP error %d - %s; " SLAPI_COMPONENT_NAME_NSPR " error %d - %s)\n", hostname, port, rc, ldap_err2string(rc), prerr, slapd_pr_strerror(prerr)); warned_bind_err = 1; } if ( errmsg ) { *errmsg = slapi_ch_smprintf("%s", ENDUSERMSG); } rc = LDAP_CONNECT_ERROR; goto unlock_and_return; } if ( serverctrls ) { int i; for( i = 0; serverctrls[ i ] != NULL; ++i ) { if ( !(strcmp( serverctrls[ i ]->ldctl_oid, LDAP_CONTROL_PWEXPIRED)) ) { /* Bind is successful but password has expired */ slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Successfully bound as %s to remote server %s:%d, " "but password has expired.\n", binddn, hostname, port); } else if ( !(strcmp( serverctrls[ i ]->ldctl_oid, LDAP_CONTROL_PWEXPIRING)) ) { /* The password is expiring in n seconds */ if ( (serverctrls[ i ]->ldctl_value.bv_val != NULL) && (serverctrls[ i ]->ldctl_value.bv_len > 0) ) { int password_expiring = atoi( serverctrls[ i ]->ldctl_value.bv_val ); slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Successfully bound as %s to remote server %s:%d, " "but password is expiring in %d seconds.\n", binddn, hostname, port, password_expiring); } } } ldap_controls_free(serverctrls); } } else if (secure == 2) { /* the start_tls operation is usually performed in slapi_ldap_bind, but since we are not binding we still need to start_tls */ if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - doing start_tls on connection 0x%p\n", conn ); } if ((rc = ldap_start_tls_s(ld, NULL, NULL))) { PRErrorCode prerr = PR_GetError(); slapi_log_err(SLAPI_LOG_ERR, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - Unable to do start_tls on connection to %s:%d " "LDAP error %d:%s NSS error %d:%s\n", hostname, port, rc, ldap_err2string(rc), prerr, slapd_pr_strerror(prerr)); goto unlock_and_return; } } conn = (cb_outgoing_conn *) slapi_ch_malloc(sizeof(cb_outgoing_conn)); conn->ld=ld; conn->status=CB_CONNSTATUS_OK; conn->refcount=0; /* incremented below */ conn->opentime=current_time(); conn->ThreadId=PR_MyThreadId(); /* store the thread id */ conn->next=NULL; if (secure) { if (pool->connarray[PR_ThreadSelf()] == NULL) { pool->connarray[PR_ThreadSelf()] = conn; } else { conn->next = pool->connarray[PR_ThreadSelf()]; pool->connarray[PR_ThreadSelf()] = conn ; } } else { if ( NULL == connprev ) { pool->conn.conn_list = conn; } else { connprev->next=conn; } } ++pool->conn.conn_list_count; if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - added new conn 0x%p, " "conn count now %d\n", conn->ld, pool->conn.conn_list_count ); } goto unlock_and_return; /* got a new one */ } if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - waiting for conn to free up\n" ); } if (!secure) slapi_wait_condvar( pool->conn.conn_list_cv, NULL ); if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - awake again\n" ); } } unlock_and_return: if ( conn != NULL ) { ++conn->refcount; *lld=conn->ld; *cc=conn; if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - ld=0x%p (concurrency now %lu)\n",*lld, conn->refcount ); } } else { if ( NULL != ld ) { slapi_ldap_unbind( ld ); } if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_get_connection - error %d\n", rc ); } } slapi_unlock_mutex(pool->conn.conn_list_mutex); return( rc ); }
void cb_release_op_connection(cb_conn_pool* pool, LDAP *lld, int dispose) { cb_outgoing_conn *conn; cb_outgoing_conn *connprev = NULL; int secure = pool->secure; int myself = 0; slapi_lock_mutex(pool->conn.conn_list_mutex); /* * find the connection structure this ld is part of */ if (secure) { myself = PR_ThreadSelf(); for (conn = pool->connarray[myself]; conn != NULL; conn = conn->next ) { if ( lld == conn->ld ) break; connprev = conn; } } else { for ( conn = pool->conn.conn_list; conn != NULL; conn = conn->next ){ if ( lld == conn->ld ) break; connprev = conn; } } if ( conn == NULL ) { /* ld not found -- unexpected */ slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_release_op_connection - ld=0x%p not found\n", lld ); } else { --conn->refcount; if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_release_op_connection - release conn 0x%p status %d refcount after release %lu\n", conn, conn->status, conn->refcount ); } if ( dispose ) { conn->status = CB_CONNSTATUS_DOWN; } if ( conn->status != CB_CONNSTATUS_OK && conn->refcount == 0 ) { /* * remove from server's connection list */ if (!secure) { if ( connprev == NULL ) { pool->conn.conn_list = conn->next; } else { connprev->next = conn->next; } } else { if ( connprev == NULL ) { pool->connarray[myself] = conn->next; } else { connprev->next = conn->next; } } --pool->conn.conn_list_count; /* * close connection and free memory */ cb_close_and_dispose_connection( conn ); } } /* * wake up a thread that is waiting for a connection */ if (!secure) slapi_notify_condvar( pool->conn.conn_list_cv, 0 ); slapi_unlock_mutex( pool->conn.conn_list_mutex ); }
static void cb_check_for_stale_connections(cb_conn_pool * pool) { cb_outgoing_conn * connprev, *conn, *conn_next; time_t curtime; int connlifetime; int myself; slapi_rwlock_rdlock(pool->rwl_config_lock); connlifetime=pool->conn.connlifetime; slapi_rwlock_unlock(pool->rwl_config_lock); connprev = NULL; conn_next = NULL; slapi_lock_mutex(pool->conn.conn_list_mutex); if (connlifetime > 0) curtime=current_time(); if (pool->secure) { myself = PR_ThreadSelf(); for (conn = pool->connarray[myself]; conn != NULL; conn = conn_next){ if ((conn->status == CB_CONNSTATUS_STALE) || (( connlifetime > 0) && (curtime - conn->opentime > connlifetime))) { if ( conn->refcount == 0 ) { if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_check_for_stale_connections - conn 0x%p idle and stale\n",conn); } --pool->conn.conn_list_count; if (connprev == NULL) { pool->connarray[myself] = conn->next ; } else { connprev->next = conn->next ; } conn_next = conn->next ; cb_close_and_dispose_connection( conn ); continue; } /* Connection is stale but in use */ /* Mark to be disposed later but let it in the backend list */ /* so that it is counted as a valid connection */ else { conn->status = CB_CONNSTATUS_STALE; } if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_check_for_stale_connections - conn 0x%p stale\n",conn); } } connprev = conn ; conn_next = conn->next; } slapi_unlock_mutex(pool->conn.conn_list_mutex); return; } for ( conn = pool->conn.conn_list; conn != NULL; conn=conn_next ) { if ((conn->status == CB_CONNSTATUS_STALE) || (( connlifetime > 0) && (curtime - conn->opentime > connlifetime))) { if ( conn->refcount == 0 ) { /* Connection idle & stale. Remove and free. */ if ( NULL == connprev ) pool->conn.conn_list = conn->next; else connprev->next=conn->next; if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_check_for_stale_connections - conn 0x%p idle and stale\n",conn); } --pool->conn.conn_list_count; conn_next=conn->next; cb_close_and_dispose_connection( conn ); continue; } /* Connection is stale but in use */ /* Mark to be disposed later but let it in the backend list */ /* so that it is counted as a valid connection */ else { conn->status = CB_CONNSTATUS_STALE; } if (cb_debug_on()) { slapi_log_err(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "cb_check_for_stale_connections - conn 0x%p stale\n",conn); } } connprev = conn; conn_next=conn->next; } /* Generate an event to wake up threads waiting */ /* for a conn to be released. Useful to detect */ /* exceeded time limit. May be expensive */ slapi_notify_condvar( pool->conn.conn_list_cv, 0 ); slapi_unlock_mutex(pool->conn.conn_list_mutex); }
void cb_stale_all_connections( cb_backend_instance * cb) { cb_outgoing_conn *conn, *next_conn, *prev_conn; int notify=0; int i, j; cb_conn_pool *pools[3]; pools[0]=cb->pool; pools[1]=cb->bind_pool; pools[2]=NULL; for (i=0; pools[i]; i++) { slapi_lock_mutex(pools[i]->conn.conn_list_mutex); for (j=0; j< MAX_CONN_ARRAY; j++) { prev_conn=NULL; for (conn = pools[i]->connarray[j]; conn != NULL; conn=next_conn) { next_conn=conn->next; if (conn->refcount > 0) { /* ** Connection is stale but in use ** Mark to be disposed later but let it in the backend list ** so that it is counted as a valid connection */ conn->status = CB_CONNSTATUS_STALE; prev_conn=conn; } else { if (prev_conn == NULL) { pools[i]->connarray[j]=next_conn; } else { prev_conn->next=next_conn; } cb_close_and_dispose_connection(conn); pools[i]->conn.conn_list_count--; } } } prev_conn = NULL ; for ( conn = pools[i]->conn.conn_list; conn != NULL; conn = next_conn ) { next_conn=conn->next; if (conn->refcount > 0) { /* ** Connection is stale but in use ** Mark to be disposed later but let it in the backend list ** so that it is counted as a valid connection */ conn->status = CB_CONNSTATUS_STALE; prev_conn=conn; } else { if (conn==pools[i]->conn.conn_list) { pools[i]->conn.conn_list=next_conn; } else if(prev_conn){ prev_conn->next=next_conn; } cb_close_and_dispose_connection(conn); pools[i]->conn.conn_list_count--; notify=1; } } if (notify && (! pools[i]->secure)) { slapi_notify_condvar( pools[i]->conn.conn_list_cv, 0 ); } slapi_unlock_mutex(pools[i]->conn.conn_list_mutex); } }
/* * Perform the agreement/domain specific configuration. * IPA stores its configuration in the tree. We use the * ds_subtree to search for the domain/realm specific * configuration entries. */ void ipa_winsync_config_refresh_domain( void *cbdata, const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree ) { IPA_WinSync_Domain_Config *iwdc = (IPA_WinSync_Domain_Config *)cbdata; Slapi_DN *config_dn = slapi_sdn_dup(ds_subtree); char *realm_filter = NULL; char *realm_attr = NULL; char *new_entry_filter = NULL; char *new_user_oc_attr = NULL; /* don't care about groups for now */ char *homedir_prefix_attr = NULL; char *login_shell_attr = NULL; char *default_group_attr = NULL; char *default_group_filter = NULL; char *default_group_name = NULL; char *real_group_filter = NULL; char *default_gid = NULL; Slapi_ValueSet *new_user_objclasses = NULL; /* don't care about groups for now */ int loopdone = 0; int search_scope = LDAP_SCOPE_SUBTREE; int ret = LDAP_SUCCESS; int acct_disable; char *inactivated_filter = NULL; char *activated_filter = NULL; char *inactivated_group_dn = NULL; char *activated_group_dn = NULL; int upg = -1; slapi_lock_mutex(theConfig.lock); realm_filter = slapi_ch_strdup(theConfig.realm_filter); realm_attr = slapi_ch_strdup(theConfig.realm_attr); new_entry_filter = slapi_ch_strdup(theConfig.new_entry_filter); new_user_oc_attr = slapi_ch_strdup(theConfig.new_user_oc_attr); homedir_prefix_attr = slapi_ch_strdup(theConfig.homedir_prefix_attr); if (theConfig.login_shell_attr) { login_shell_attr = slapi_ch_strdup(theConfig.login_shell_attr); } default_group_attr = slapi_ch_strdup(theConfig.default_group_attr); default_group_filter = slapi_ch_strdup(theConfig.default_group_filter); acct_disable = theConfig.acct_disable; if (acct_disable != ACCT_DISABLE_NONE) { if (theConfig.inactivated_filter) { inactivated_filter = slapi_ch_strdup(theConfig.inactivated_filter); } if (theConfig.activated_filter) { activated_filter = slapi_ch_strdup(theConfig.activated_filter); } } slapi_unlock_mutex(theConfig.lock); /* starting at ds_subtree, search for the entry containing the Kerberos realm to use */ slapi_ch_free_string(&iwdc->realm_name); while(!loopdone && !slapi_sdn_isempty(config_dn)) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, realm_filter, realm_attr, NULL, &iwdc->realm_name); if ((0 == ret) && iwdc->realm_name) { loopdone = 1; } else if ((LDAP_NO_SUCH_OBJECT == ret) && !iwdc->realm_name) { /* try again */ Slapi_DN *parent_dn = slapi_sdn_new(); slapi_sdn_get_parent(config_dn, parent_dn); slapi_sdn_free(&config_dn); config_dn = parent_dn; } else { /* error */ goto out; } } if (!iwdc->realm_name) { /* error - could not find the IPA config entry with the realm name */ LOG_FATAL("Error: could not find the entry containing the realm name " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), realm_filter, realm_attr); goto out; } /* look for the entry containing the default objectclasses to add to new entries */ ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, new_user_oc_attr, &new_user_objclasses, NULL); if (!new_user_objclasses) { /* error - could not find the entry containing list of objectclasses */ LOG_FATAL("Error: could not find the entry containing the new user objectclass list " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, new_user_oc_attr); goto out; } /* get the home directory prefix value */ /* note - this is in the same entry as the new entry template, so use the same filter */ slapi_ch_free_string(&iwdc->homedir_prefix); ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, homedir_prefix_attr, NULL, &iwdc->homedir_prefix); if (!iwdc->homedir_prefix) { /* error - could not find the home dir prefix */ LOG_FATAL("Error: could not find the entry containing the home directory prefix " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, homedir_prefix_attr); goto out; } /* get the login shell value */ /* note - this is in the same entry as the new entry template, so use the same filter */ slapi_ch_free_string(&iwdc->login_shell); if (login_shell_attr) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, login_shell_attr, NULL, &iwdc->login_shell); if (!iwdc->login_shell) { LOG("Warning: could not find the entry containing the login shell " "attribute [%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, login_shell_attr); } } if (!iwdc->login_shell) { /* could not find the login shell or was not configured */ LOG("Warning: no login shell configured!"); } /* find the default group - the entry above contains the group name, but we need the gidNumber for posixAccount - so first find the entry and attr value which has the group name, then lookup the group number from the group name */ ret = internal_find_entry_get_attr_val(config_dn, search_scope, new_entry_filter, default_group_attr, NULL, &default_group_name); if (!default_group_name) { /* error - could not find the default group name */ LOG_FATAL("Error: could not find the entry containing the default group name " "[%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, default_group_attr); goto out; } /* check if User Private Groups are enabled */ upg = ipa_winsync_upg_enabled(ds_subtree); /* next, find the group whose name is default_group_name - construct the filter based on the filter attribute value - assumes the group name is stored in the cn attribute value, and the gidNumber in the gidNumber attribute value */ real_group_filter = slapi_ch_smprintf("(&(cn=%s)%s)", default_group_name, default_group_filter); ret = internal_find_entry_get_attr_val(config_dn, search_scope, real_group_filter, "gidNumber", NULL, &default_gid); if (!default_gid) { /* error - could not find the default gidNumber This is not a fatal error if User Private Groups (UPG) are enabled. */ if (upg) { LOG_FATAL("Error: could not find the entry containing the default gidNumber " "UPG [%d] ds subtree [%s] filter [%s] attr [%s]\n", ret, slapi_sdn_get_dn(ds_subtree), new_entry_filter, "gidNumber"); goto out; } else { ret = LDAP_SUCCESS; } } /* If we are syncing account disable, we need to find the groups used to denote active and inactive users e.g. dn: cn=inactivated,cn=account inactivation,cn=accounts,$SUFFIX dn: cn=Activated,cn=Account Inactivation,cn=accounts,$SUFFIX */ if (acct_disable != ACCT_DISABLE_NONE) { if (inactivated_filter) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, inactivated_filter, "dn", NULL, &inactivated_group_dn); if (!inactivated_group_dn) { /* error - could not find the inactivated group dn */ LOG("Could not find the DN of the inactivated users group " "[%d] ds subtree [%s] filter [%s]. Ignoring\n", ret, slapi_sdn_get_dn(ds_subtree), inactivated_filter); goto out; } } if (activated_filter) { ret = internal_find_entry_get_attr_val(config_dn, search_scope, activated_filter, "dn", NULL, &activated_group_dn); if (!activated_group_dn) { /* error - could not find the activated group dn */ LOG("Could not find the DN of the activated users group " "[%d] ds subtree [%s] filter [%s]. Ignoring\n", ret, slapi_sdn_get_dn(ds_subtree), activated_filter); goto out; } } } /* ok, we have our values */ /* first, clear out the old domain config */ slapi_entry_free(iwdc->domain_e); iwdc->domain_e = NULL; /* next, copy the global attr config */ slapi_lock_mutex(theConfig.lock); iwdc->domain_e = slapi_entry_dup(theConfig.config_e); slapi_unlock_mutex(theConfig.lock); /* set the objectclasses in the domain_e */ slapi_entry_attr_delete(iwdc->domain_e, "objectclass"); /* this copies new_user_objclasses */ slapi_entry_add_valueset(iwdc->domain_e, "objectclass", new_user_objclasses); /* When UPG is disabled, set the default gid number */ if (upg && default_gid) { slapi_entry_attr_set_charptr(iwdc->domain_e, "gidNumber", default_gid); } slapi_ch_free_string(&iwdc->inactivated_group_dn); iwdc->inactivated_group_dn = inactivated_group_dn; inactivated_group_dn = NULL; slapi_ch_free_string(&iwdc->activated_group_dn); iwdc->activated_group_dn = activated_group_dn; activated_group_dn = NULL; out: slapi_valueset_free(new_user_objclasses); slapi_sdn_free(&config_dn); slapi_ch_free_string(&realm_filter); slapi_ch_free_string(&realm_attr); slapi_ch_free_string(&new_entry_filter); slapi_ch_free_string(&new_user_oc_attr); slapi_ch_free_string(&homedir_prefix_attr); slapi_ch_free_string(&login_shell_attr); slapi_ch_free_string(&default_group_attr); slapi_ch_free_string(&default_group_filter); slapi_ch_free_string(&default_group_name); slapi_ch_free_string(&real_group_filter); slapi_ch_free_string(&default_gid); slapi_ch_free_string(&inactivated_filter); slapi_ch_free_string(&inactivated_group_dn); slapi_ch_free_string(&activated_filter); slapi_ch_free_string(&activated_group_dn); if (LDAP_SUCCESS != ret) { slapi_ch_free_string(&iwdc->realm_name); slapi_ch_free_string(&iwdc->homedir_prefix); slapi_ch_free_string(&iwdc->login_shell); slapi_entry_free(iwdc->domain_e); iwdc->domain_e = NULL; } return; }
static int ipa_winsync_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { PRBool flatten = PR_TRUE; char *realm_filter = NULL; char *realm_attr = NULL; char *new_entry_filter = NULL; char *new_user_oc_attr = NULL; /* don't care about groups for now */ char *homedir_prefix_attr = NULL; char *login_shell_attr = NULL; char *default_group_attr = NULL; char *default_group_filter = NULL; char *acct_disable = NULL; int acct_disable_int; char *inactivated_filter = NULL; char *activated_filter = NULL; char **attrsvals = NULL; int ii; Slapi_Attr *testattr = NULL; PRBool forceSync = PR_FALSE; *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ /* get flatten value */ if (!slapi_entry_attr_find(e, IPA_WINSYNC_USER_FLATTEN, &testattr) && (NULL != testattr)) { flatten = slapi_entry_attr_get_bool(e, IPA_WINSYNC_USER_FLATTEN); } /* get realm filter */ if (!(realm_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_REALM_FILTER_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_REALM_FILTER_ATTR); goto done3; } /* get realm attr */ if (!(realm_attr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_REALM_ATTR_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_REALM_ATTR_ATTR); goto done3; } /* get new_entry_filter */ if (!(new_entry_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR); goto done3; } /* get new_user_oc_attr */ if (!(new_user_oc_attr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_NEW_USER_OC_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_NEW_USER_OC_ATTR); goto done3; } /* get homedir_prefix_attr */ if (!(homedir_prefix_attr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_HOMEDIR_PREFIX_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_HOMEDIR_PREFIX_ATTR); goto done3; } /* get login_shell_attr */ login_shell_attr = slapi_entry_attr_get_charptr(e, IPA_WINSYNC_LOGIN_SHELL_ATTR); if (!login_shell_attr) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Warning: no value given for %s", IPA_WINSYNC_LOGIN_SHELL_ATTR); } /* get default_group_attr */ if (!(default_group_attr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_DEFAULTGROUP_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_DEFAULTGROUP_ATTR); goto done3; } /* get default_group_filter */ if (!(default_group_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR); goto done3; } /* get the list of attributes & values */ /* get new_user_oc_attr */ if (!(attrsvals = slapi_entry_attr_get_charray( e, IPA_WINSYNC_NEW_USER_ATTRS_VALS))) { LOG("Info: no default attributes and values given in [%s]\n", IPA_WINSYNC_NEW_USER_ATTRS_VALS); } /* get acct disable sync value */ if (!(acct_disable = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_ACCT_DISABLE))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_ACCT_DISABLE); goto done3; } acct_disable_int = parse_acct_disable(acct_disable); if (ACCT_DISABLE_INVALID == acct_disable_int) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: invalid value [%s] given for [%s] - valid " "values are " IPA_WINSYNC_ACCT_DISABLE_NONE ", " IPA_WINSYNC_ACCT_DISABLE_TO_AD ", " IPA_WINSYNC_ACCT_DISABLE_TO_DS ", or " IPA_WINSYNC_ACCT_DISABLE_BOTH, acct_disable, IPA_WINSYNC_ACCT_DISABLE); goto done3; } if (acct_disable_int != ACCT_DISABLE_NONE) { /* get inactivated group filter */ if (!(inactivated_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_INACTIVATED_FILTER))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No value given for %s - required for account " "disable sync, ignoring", IPA_WINSYNC_INACTIVATED_FILTER); } /* get activated group filter */ if (!(activated_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_ACTIVATED_FILTER))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No value given for %s - required for account " "disable sync, ignoring", IPA_WINSYNC_ACTIVATED_FILTER); } } /* get forceSync value */ if (!slapi_entry_attr_find(e, IPA_WINSYNC_FORCE_SYNC, &testattr) && (NULL != testattr)) { forceSync = slapi_entry_attr_get_bool(e, IPA_WINSYNC_FORCE_SYNC); } /* if we got here, we have valid values for everything set the config entry */ slapi_lock_mutex(theConfig.lock); slapi_entry_free(theConfig.config_e); theConfig.config_e = slapi_entry_alloc(); slapi_entry_init(theConfig.config_e, slapi_ch_strdup(""), NULL); /* format of *attrsvals is "attrname value" */ /* attrname <space> value */ /* value may contain spaces - attrname is everything up to the first space - value is everything after the first space */ for (ii = 0; attrsvals && attrsvals[ii]; ++ii) { int rc; Slapi_Value *sva[2]; Slapi_Value *sv = NULL; char *val = strchr(attrsvals[ii], ' '); if (!val || !*(val+1)) { /* incorrect format or no value */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value or incorrect value given for [%s] " "value [%s] index [%d] - correct format is attrname SPACE value", IPA_WINSYNC_NEW_USER_ATTRS_VALS, attrsvals[ii], ii); goto done3; } *val++ = '\0'; /* separate attr from val */ sv = slapi_value_new_string(val); sva[0] = sv; sva[1] = NULL; if ((rc = slapi_entry_add_values_sv(theConfig.config_e, attrsvals[ii], sva)) && (rc != LDAP_SUCCESS)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: could not add value [%s] for attribute name " "[%s] - ldap error [%d: %s]", val, attrsvals[ii], rc, ldap_err2string(rc)); slapi_entry_free(theConfig.config_e); theConfig.config_e = NULL; slapi_value_free(&sv); goto done3; } slapi_value_free(&sv); } /* all of the attrs and vals have been set - set the other values */ slapi_ch_free_string(&theConfig.realm_filter); theConfig.realm_filter = realm_filter; realm_filter = NULL; slapi_ch_free_string(&theConfig.realm_attr); theConfig.realm_attr = realm_attr; realm_attr = NULL; slapi_ch_free_string(&theConfig.new_entry_filter); theConfig.new_entry_filter = new_entry_filter; new_entry_filter = NULL; slapi_ch_free_string(&theConfig.new_user_oc_attr); theConfig.new_user_oc_attr = new_user_oc_attr; new_user_oc_attr = NULL; slapi_ch_free_string(&theConfig.homedir_prefix_attr); theConfig.homedir_prefix_attr = homedir_prefix_attr; homedir_prefix_attr = NULL; if (login_shell_attr) { slapi_ch_free_string(&theConfig.login_shell_attr); theConfig.login_shell_attr = login_shell_attr; login_shell_attr = NULL; } slapi_ch_free_string(&theConfig.default_group_attr); theConfig.default_group_attr = default_group_attr; default_group_attr = NULL; slapi_ch_free_string(&theConfig.default_group_filter); theConfig.default_group_filter = default_group_filter; default_group_filter = NULL; theConfig.flatten = flatten; theConfig.acct_disable = parse_acct_disable(acct_disable); slapi_ch_free_string(&theConfig.inactivated_filter); theConfig.inactivated_filter = inactivated_filter; inactivated_filter = NULL; slapi_ch_free_string(&theConfig.activated_filter); theConfig.activated_filter = activated_filter; activated_filter = NULL; theConfig.forceSync = forceSync; /* success */ *returncode = LDAP_SUCCESS; done3: slapi_unlock_mutex(theConfig.lock); slapi_ch_free_string(&realm_filter); slapi_ch_free_string(&realm_attr); slapi_ch_free_string(&new_entry_filter); slapi_ch_free_string(&new_user_oc_attr); slapi_ch_free_string(&homedir_prefix_attr); slapi_ch_free_string(&login_shell_attr); slapi_ch_free_string(&default_group_attr); slapi_ch_free_string(&default_group_filter); slapi_ch_array_free(attrsvals); attrsvals = NULL; slapi_ch_free_string(&acct_disable); slapi_ch_free_string(&inactivated_filter); slapi_ch_free_string(&activated_filter); if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } }
static void linked_attrs_fixup_links(struct configEntry *config) { Slapi_PBlock *pb = slapi_pblock_new(); char *del_filter = NULL; char *add_filter = NULL; del_filter = slapi_ch_smprintf("%s=*", config->managedtype); add_filter = slapi_ch_smprintf("%s=*", config->linktype); /* Lock the attribute pair. */ slapi_lock_mutex(config->lock); if (config->scope) { /* Find all entries with the managed type present * within the scope and remove the managed type. */ slapi_search_internal_set_pb(pb, config->scope, LDAP_SCOPE_SUBTREE, del_filter, 0, 0, 0, 0, linked_attrs_get_plugin_id(), 0); slapi_search_internal_callback_pb(pb, config->managedtype, 0, linked_attrs_remove_backlinks_callback, 0); /* Clean out pblock for reuse. */ slapi_pblock_init(pb); /* Find all entries with the link type present within the * scope and add backlinks to the entries they point to. */ slapi_search_internal_set_pb(pb, config->scope, LDAP_SCOPE_SUBTREE, add_filter, 0, 0, 0, 0, linked_attrs_get_plugin_id(), 0); slapi_search_internal_callback_pb(pb, config, 0, linked_attrs_add_backlinks_callback, 0); } else { /* Loop through all non-private backend suffixes and * remove the managed type from any entry that has it. * We then find any entry with the linktype present and * generate the proper backlinks. */ void *node = NULL; Slapi_DN * suffix = slapi_get_first_suffix (&node, 0); while (suffix) { slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(suffix), LDAP_SCOPE_SUBTREE, del_filter, 0, 0, 0, 0, linked_attrs_get_plugin_id(), 0); slapi_search_internal_callback_pb(pb, config->managedtype, 0, linked_attrs_remove_backlinks_callback, 0); /* Clean out pblock for reuse. */ slapi_pblock_init(pb); slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(suffix), LDAP_SCOPE_SUBTREE, add_filter, 0, 0, 0, 0, linked_attrs_get_plugin_id(), 0); slapi_search_internal_callback_pb(pb, config, 0, linked_attrs_add_backlinks_callback, 0); /* Clean out pblock for reuse. */ slapi_pblock_init(pb); suffix = slapi_get_next_suffix (&node, 0); } } /* Unlock the attribute pair. */ slapi_unlock_mutex(config->lock); slapi_ch_free_string(&del_filter); slapi_ch_free_string(&add_filter); slapi_pblock_destroy(pb); }