Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
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 );
  }
}
Beispiel #5
0
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");
	       	}
		
	}
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
	}
}
Beispiel #8
0
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);
}
Beispiel #9
0
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 ;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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 );
}
Beispiel #13
0
/*
 * 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;
}
Beispiel #14
0
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 );
}
Beispiel #15
0
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 );
}
Beispiel #16
0
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);
}
Beispiel #17
0
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);
	}
}
Beispiel #18
0
/*
 * 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;
}
Beispiel #19
0
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;
    }
}
Beispiel #20
0
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);
}