Example #1
0
File: sasl.c Project: MPlatform/mdb
static int
#else
static void
#endif
slap_auxprop_lookup(
	void *glob_context,
	sasl_server_params_t *sparams,
	unsigned flags,
	const char *user,
	unsigned ulen)
{
	OperationBuffer opbuf = {{ NULL }};
	Operation *op = (Operation *)&opbuf;
	int i, doit = 0;
	Connection *conn = NULL;
	lookup_info sl;
	int rc = LDAP_SUCCESS;
#ifdef SLAP_AUXPROP_DONTUSECOPY
	int dontUseCopy = 0;
	BackendDB *dontUseCopy_bd = NULL;
#endif /* SLAP_AUXPROP_DONTUSECOPY */

	sl.list = sparams->utils->prop_get( sparams->propctx );
	sl.sparams = sparams;
	sl.flags = flags;

	/* Find our DN and conn first */
	for( i = 0; sl.list[i].name; i++ ) {
		if ( sl.list[i].name[0] == '*' ) {
			if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) {
				if ( sl.list[i].values && sl.list[i].values[0] )
					AC_MEMCPY( &conn, sl.list[i].values[0], sizeof( conn ) );
				continue;
			}
			if ( flags & SASL_AUXPROP_AUTHZID ) {
				if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZLEN] )) {
					if ( sl.list[i].values && sl.list[i].values[0] )
						AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0],
							sizeof( op->o_req_ndn.bv_len ) );
				} else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZ] )) {
					if ( sl.list[i].values )
						op->o_req_ndn.bv_val = (char *)sl.list[i].values[0];
					break;
				}
			}

			if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) {
				if ( sl.list[i].values && sl.list[i].values[0] )
					AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0],
						sizeof( op->o_req_ndn.bv_len ) );
			} else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) {
				if ( sl.list[i].values ) {
					op->o_req_ndn.bv_val = (char *)sl.list[i].values[0];
					if ( !(flags & SASL_AUXPROP_AUTHZID) )
						break;
				}
			}
#ifdef SLAP_AUXPROP_DONTUSECOPY
			if ( slap_dontUseCopy_propnames != NULL ) {
				int j;
				struct berval bv;
				ber_str2bv( &sl.list[i].name[1], 0, 1, &bv );
				for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ]); j++ ) {
					if ( bvmatch( &bv, &slap_dontUseCopy_propnames[ j ] ) ) {
						dontUseCopy = 1;
						break;
					}
				}
			}
#endif /* SLAP_AUXPROP_DONTUSECOPY */
		}
	}

	/* Now see what else needs to be fetched */
	for( i = 0; sl.list[i].name; i++ ) {
		const char *name = sl.list[i].name;

		if ( name[0] == '*' ) {
			if ( flags & SASL_AUXPROP_AUTHZID ) continue;
			/* Skip our private properties */
			if ( !strcmp( name, slap_propnames[0] )) {
				i += SLAP_SASL_PROP_COUNT - 1;
				continue;
			}
			name++;
		} else if ( !(flags & SASL_AUXPROP_AUTHZID ) )
			continue;

		if ( sl.list[i].values ) {
			if ( !(flags & SASL_AUXPROP_OVERRIDE) ) continue;
		}
		doit = 1;
		break;
	}

	if (doit) {
		slap_callback cb = { NULL, sasl_ap_lookup, NULL, NULL };

		cb.sc_private = &sl;

		op->o_bd = select_backend( &op->o_req_ndn, 1 );

		if ( op->o_bd ) {
			/* For rootdn, see if we can use the rootpw */
			if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) &&
				!BER_BVISEMPTY( &op->o_bd->be_rootpw )) {
				struct berval cbv = BER_BVNULL;

				/* If there's a recognized scheme, see if it's CLEARTEXT */
				if ( lutil_passwd_scheme( op->o_bd->be_rootpw.bv_val )) {
					if ( !strncasecmp( op->o_bd->be_rootpw.bv_val,
						sc_cleartext.bv_val, sc_cleartext.bv_len )) {

						/* If it's CLEARTEXT, skip past scheme spec */
						cbv.bv_len = op->o_bd->be_rootpw.bv_len -
							sc_cleartext.bv_len;
						if ( cbv.bv_len ) {
							cbv.bv_val = op->o_bd->be_rootpw.bv_val +
								sc_cleartext.bv_len;
						}
					}
				/* No scheme, use the whole value */
				} else {
					cbv = op->o_bd->be_rootpw;
				}
				if ( !BER_BVISEMPTY( &cbv )) {
					for( i = 0; sl.list[i].name; i++ ) {
						const char *name = sl.list[i].name;

						if ( name[0] == '*' ) {
							if ( flags & SASL_AUXPROP_AUTHZID ) continue;
								name++;
						} else if ( !(flags & SASL_AUXPROP_AUTHZID ) )
							continue;

						if ( !strcasecmp(name,"userPassword") ) {
							sl.sparams->utils->prop_set( sl.sparams->propctx,
								sl.list[i].name, cbv.bv_val, cbv.bv_len );
							break;
						}
					}
				}
			}

#ifdef SLAP_AUXPROP_DONTUSECOPY
			if ( SLAP_SHADOW( op->o_bd ) && dontUseCopy ) {
				dontUseCopy_bd = op->o_bd;
				op->o_bd = frontendDB;
			}

retry_dontUseCopy:;
#endif /* SLAP_AUXPROP_DONTUSECOPY */

			if ( op->o_bd->be_search ) {
				SlapReply rs = {REP_RESULT};
#ifdef SLAP_AUXPROP_DONTUSECOPY
				LDAPControl **save_ctrls = NULL, c;
				int save_dontUseCopy;
#endif /* SLAP_AUXPROP_DONTUSECOPY */

				op->o_hdr = conn->c_sasl_bindop->o_hdr;
				op->o_controls = opbuf.ob_controls;
				op->o_tag = LDAP_REQ_SEARCH;
				op->o_dn = conn->c_ndn;
				op->o_ndn = conn->c_ndn;
				op->o_callback = &cb;
				slap_op_time( &op->o_time, &op->o_tincr );
				op->o_do_not_cache = 1;
				op->o_is_auth_check = 1;
				op->o_req_dn = op->o_req_ndn;
				op->ors_scope = LDAP_SCOPE_BASE;
				op->ors_deref = LDAP_DEREF_NEVER;
				op->ors_tlimit = SLAP_NO_LIMIT;
				op->ors_slimit = 1;
				op->ors_filter = &generic_filter;
				op->ors_filterstr = generic_filterstr;
				op->o_authz = conn->c_authz;
				/* FIXME: we want all attributes, right? */
				op->ors_attrs = NULL;

#ifdef SLAP_AUXPROP_DONTUSECOPY
				if ( dontUseCopy ) {
					save_dontUseCopy = op->o_dontUseCopy;
					if ( !op->o_dontUseCopy ) {
						int cnt = 0;
						save_ctrls = op->o_ctrls;
						if ( op->o_ctrls ) {
							for ( ; op->o_ctrls[ cnt ]; cnt++ )
								;
						}
						op->o_ctrls = op->o_tmpcalloc( sizeof(LDAPControl *), cnt + 2, op->o_tmpmemctx );
						if ( cnt ) {
							for ( cnt = 0; save_ctrls[ cnt ]; cnt++ ) {
								op->o_ctrls[ cnt ] = save_ctrls[ cnt ];
							}
						}
						c.ldctl_oid = LDAP_CONTROL_DONTUSECOPY;
						c.ldctl_iscritical = 1;
						BER_BVZERO( &c.ldctl_value );
						op->o_ctrls[ cnt ] = &c;
					}
					op->o_dontUseCopy = SLAP_CONTROL_CRITICAL;
				}
#endif /* SLAP_AUXPROP_DONTUSECOPY */

				rc = op->o_bd->be_search( op, &rs );

#ifdef SLAP_AUXPROP_DONTUSECOPY
				if ( dontUseCopy ) {
					if ( save_ctrls != op->o_ctrls ) {
						op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
						op->o_ctrls = save_ctrls;
						op->o_dontUseCopy = save_dontUseCopy;
					}

					if ( rs.sr_err == LDAP_UNAVAILABLE && slap_dontUseCopy_ignore )
					{
						op->o_bd = dontUseCopy_bd;
						dontUseCopy = 0;
						goto retry_dontUseCopy;
					}
				}
#endif /* SLAP_AUXPROP_DONTUSECOPY */
			}
		}
	}
#if SASL_VERSION_FULL >= 0x020118
	return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK;
#endif
}
Example #2
0
static int
#else
static void
#endif
slap_auxprop_lookup(
	void *glob_context,
	sasl_server_params_t *sparams,
	unsigned flags,
	const char *user,
	unsigned ulen)
{
	OperationBuffer opbuf = {{ NULL }};
	Operation *op = (Operation *)&opbuf;
	int i, doit = 0;
	Connection *conn = NULL;
	lookup_info sl;
	int rc = LDAP_SUCCESS;

	sl.list = sparams->utils->prop_get( sparams->propctx );
	sl.sparams = sparams;
	sl.flags = flags;

	/* Find our DN and conn first */
	for( i = 0; sl.list[i].name; i++ ) {
		if ( sl.list[i].name[0] == '*' ) {
			if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) {
				if ( sl.list[i].values && sl.list[i].values[0] )
					AC_MEMCPY( &conn, sl.list[i].values[0], sizeof( conn ) );
				continue;
			}
			if ( flags & SASL_AUXPROP_AUTHZID ) {
				if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZLEN] )) {
					if ( sl.list[i].values && sl.list[i].values[0] )
						AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0],
							sizeof( op->o_req_ndn.bv_len ) );
				} else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZ] )) {
					if ( sl.list[i].values )
						op->o_req_ndn.bv_val = (char *)sl.list[i].values[0];
					break;
				}
			}

			if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) {
				if ( sl.list[i].values && sl.list[i].values[0] )
					AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0],
						sizeof( op->o_req_ndn.bv_len ) );
			} else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) {
				if ( sl.list[i].values ) {
					op->o_req_ndn.bv_val = (char *)sl.list[i].values[0];
					if ( !(flags & SASL_AUXPROP_AUTHZID) )
						break;
				}
			}
		}
	}

	/* we don't know anything about this, ignore it */
	if ( !conn ) {
		rc = LDAP_SUCCESS;
		goto done;
	}

	/* Now see what else needs to be fetched */
	for( i = 0; sl.list[i].name; i++ ) {
		const char *name = sl.list[i].name;

		if ( name[0] == '*' ) {
			if ( flags & SASL_AUXPROP_AUTHZID ) continue;
			/* Skip our private properties */
			if ( !strcmp( name, slap_propnames[0] )) {
				i += SLAP_SASL_PROP_COUNT - 1;
				continue;
			}
			name++;
		} else if ( !(flags & SASL_AUXPROP_AUTHZID ) )
			continue;

		if ( sl.list[i].values ) {
			if ( !(flags & SASL_AUXPROP_OVERRIDE) ) continue;
		}
		doit = 1;
		break;
	}

	if (doit) {
		slap_callback cb = { NULL, sasl_ap_lookup, NULL, NULL };

		cb.sc_private = &sl;

		op->o_bd = select_backend( &op->o_req_ndn, 1 );

		if ( op->o_bd ) {
			/* For rootdn, see if we can use the rootpw */
			if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) &&
				!BER_BVISEMPTY( &op->o_bd->be_rootpw )) {
				struct berval cbv = BER_BVNULL;

				/* If there's a recognized scheme, see if it's CLEARTEXT */
				if ( lutil_passwd_scheme( op->o_bd->be_rootpw.bv_val )) {
					if ( !strncasecmp( op->o_bd->be_rootpw.bv_val,
						sc_cleartext.bv_val, sc_cleartext.bv_len )) {

						/* If it's CLEARTEXT, skip past scheme spec */
						cbv.bv_len = op->o_bd->be_rootpw.bv_len -
							sc_cleartext.bv_len;
						if ( cbv.bv_len ) {
							cbv.bv_val = op->o_bd->be_rootpw.bv_val +
								sc_cleartext.bv_len;
						}
					}
				/* No scheme, use the whole value */
				} else {
					cbv = op->o_bd->be_rootpw;
				}
				if ( !BER_BVISEMPTY( &cbv )) {
					for( i = 0; sl.list[i].name; i++ ) {
						const char *name = sl.list[i].name;

						if ( name[0] == '*' ) {
							if ( flags & SASL_AUXPROP_AUTHZID ) continue;
								name++;
						} else if ( !(flags & SASL_AUXPROP_AUTHZID ) )
							continue;

						if ( !strcasecmp(name,"userPassword") ) {
							sl.sparams->utils->prop_set( sl.sparams->propctx,
								sl.list[i].name, cbv.bv_val, cbv.bv_len );
							break;
						}
					}
				}
			}

			if ( op->o_bd->be_search ) {
				SlapReply rs = {REP_RESULT};
				op->o_hdr = conn->c_sasl_bindop->o_hdr;
				op->o_controls = opbuf.ob_controls;
				op->o_tag = LDAP_REQ_SEARCH;
				op->o_dn = conn->c_ndn;
				op->o_ndn = conn->c_ndn;
				op->o_callback = &cb;
				slap_op_time( &op->o_time, &op->o_tincr );
				op->o_do_not_cache = 1;
				op->o_is_auth_check = 1;
				op->o_req_dn = op->o_req_ndn;
				op->ors_scope = LDAP_SCOPE_BASE;
				op->ors_deref = LDAP_DEREF_NEVER;
				op->ors_tlimit = SLAP_NO_LIMIT;
				op->ors_slimit = 1;
				op->ors_filter = &generic_filter;
				op->ors_filterstr = generic_filterstr;
				op->o_authz = conn->c_authz;
				/* FIXME: we want all attributes, right? */
				op->ors_attrs = NULL;

				rc = op->o_bd->be_search( op, &rs );
			}
		}
	}
done:;
#if SASL_VERSION_FULL >= 0x020118
	return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK;
#endif
}
Example #3
0
File: sasl.c Project: MPlatform/mdb
static int
sasl_ap_lookup( Operation *op, SlapReply *rs )
{
	BerVarray bv;
	AttributeDescription *ad;
	Attribute *a;
	const char *text;
	int rc, i;
	lookup_info *sl = (lookup_info *)op->o_callback->sc_private;

	/* return the actual error code,
	 * to allow caller to handle specific errors
	 */
	if (rs->sr_type != REP_SEARCH) return rs->sr_err;

	for( i = 0; sl->list[i].name; i++ ) {
		const char *name = sl->list[i].name;

		if ( name[0] == '*' ) {
			if ( sl->flags & SASL_AUXPROP_AUTHZID ) continue;
			/* Skip our private properties */
			if ( !strcmp( name, slap_propnames[0] )) {
				i += SLAP_SASL_PROP_COUNT - 1;
				continue;
			}
			name++;
		} else if ( !(sl->flags & SASL_AUXPROP_AUTHZID ) )
			continue;

		if ( sl->list[i].values ) {
			if ( !(sl->flags & SASL_AUXPROP_OVERRIDE) ) continue;
		}
		ad = NULL;
		rc = slap_str2ad( name, &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE,
				"slap_ap_lookup: str2ad(%s): %s\n", name, text, 0 );
			continue;
		}

		/* If it's the rootdn and a rootpw was present, we already set
		 * it so don't override it here.
		 */
		if ( ad == slap_schema.si_ad_userPassword && sl->list[i].values && 
			be_isroot_dn( op->o_bd, &op->o_req_ndn ))
			continue;

		a = attr_find( rs->sr_entry->e_attrs, ad );
		if ( !a ) continue;
		if ( ! access_allowed( op, rs->sr_entry, ad, NULL, ACL_AUTH, NULL ) ) {
			continue;
		}
		if ( sl->list[i].values && ( sl->flags & SASL_AUXPROP_OVERRIDE ) ) {
			sl->sparams->utils->prop_erase( sl->sparams->propctx,
			sl->list[i].name );
		}
		for ( bv = a->a_vals; bv->bv_val; bv++ ) {
			/* ITS#3846 don't give hashed passwords to SASL */
			if ( ad == slap_schema.si_ad_userPassword &&
				bv->bv_val[0] == '{' /*}*/ )
			{
				if ( lutil_passwd_scheme( bv->bv_val ) ) {
					/* If it's not a recognized scheme, just assume it's
					 * a cleartext password that happened to include brackets.
					 *
					 * If it's a recognized scheme, skip this value, unless the
					 * scheme is {CLEARTEXT}. In that case, skip over the
					 * scheme name and use the remainder. If there is nothing
					 * past the scheme name, skip this value.
					 */
#ifdef SLAPD_CLEARTEXT
					if ( !strncasecmp( bv->bv_val, sc_cleartext.bv_val,
						sc_cleartext.bv_len )) {
						struct berval cbv;
						cbv.bv_len = bv->bv_len - sc_cleartext.bv_len;
						if ( cbv.bv_len > 0 ) {
							cbv.bv_val = bv->bv_val + sc_cleartext.bv_len;
							sl->sparams->utils->prop_set( sl->sparams->propctx,
								sl->list[i].name, cbv.bv_val, cbv.bv_len );
						}
					}
#endif
					continue;
				}
			}
			sl->sparams->utils->prop_set( sl->sparams->propctx,
				sl->list[i].name, bv->bv_val, bv->bv_len );
		}
	}
	return LDAP_SUCCESS;
}
Example #4
0
static int
dds_op_add( Operation *op, SlapReply *rs )
{
	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
	dds_info_t	*di = on->on_bi.bi_private;
	int		is_dynamicObject;

	if ( DDS_OFF( di ) ) {
		return SLAP_CB_CONTINUE;
	}

	is_dynamicObject = is_entry_dynamicObject( op->ora_e );

	/* FIXME: do not allow this right now, pending clarification */
	if ( is_dynamicObject ) {
		rs->sr_err = LDAP_SUCCESS;

		if ( is_entry_referral( op->ora_e ) ) {
			rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
			rs->sr_text = "a referral cannot be a dynamicObject";

		} else if ( is_entry_alias( op->ora_e ) ) {
			rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
			rs->sr_text = "an alias cannot be a dynamicObject";
		}

		if ( rs->sr_err != LDAP_SUCCESS ) {
			op->o_bd->bd_info = (BackendInfo *)on->on_info;
			send_ldap_result( op, rs );
			return rs->sr_err;
		}
	}

	/* we don't allow dynamicObjects to have static subordinates */
	if ( !dn_match( &op->o_req_ndn, &op->o_bd->be_nsuffix[ 0 ] ) ) {
		struct berval	p_ndn;
		Entry		*e = NULL;
		int		rc;
		BackendInfo	*bi = op->o_bd->bd_info;

		dnParent( &op->o_req_ndn, &p_ndn );
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
		rc = be_entry_get_rw( op, &p_ndn,
			slap_schema.si_oc_dynamicObject, NULL, 0, &e );
		if ( rc == LDAP_SUCCESS && e != NULL ) {
			if ( !is_dynamicObject ) {
				/* return referral only if "disclose"
				 * is granted on the object */
				if ( ! access_allowed( op, e,
						slap_schema.si_ad_entry,
						NULL, ACL_DISCLOSE, NULL ) )
				{
					rc = rs->sr_err = LDAP_NO_SUCH_OBJECT;
					send_ldap_result( op, rs );

				} else {
					rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
					send_ldap_error( op, rs, rc, "no static subordinate entries allowed for dynamicObject" );
				}
			}

			be_entry_release_r( op, e );
			if ( rc != LDAP_SUCCESS ) {
				return rc;
			}
		}
		op->o_bd->bd_info = bi;
	}

	/* handle dynamic object operational attr(s) */
	if ( is_dynamicObject ) {
		time_t		ttl, expire;
		char		ttlbuf[STRLENOF("31557600") + 1];
		char		tsbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
		struct berval	bv;

		if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
			ldap_pvt_thread_mutex_lock( &di->di_mutex );
			rs->sr_err = ( di->di_max_dynamicObjects &&
				di->di_num_dynamicObjects >= di->di_max_dynamicObjects );
			ldap_pvt_thread_mutex_unlock( &di->di_mutex );
			if ( rs->sr_err ) {
				op->o_bd->bd_info = (BackendInfo *)on->on_info;
				send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
					"too many dynamicObjects in context" );
				return rs->sr_err;
			}
		}

		ttl = DDS_DEFAULT_TTL( di );

		/* assert because should be checked at configure */
		assert( ttl <= DDS_RF2589_MAX_TTL );

		bv.bv_val = ttlbuf;
		bv.bv_len = snprintf( ttlbuf, sizeof( ttlbuf ), "%ld", ttl );
		assert( bv.bv_len < sizeof( ttlbuf ) );

		/* FIXME: apparently, values in op->ora_e are malloc'ed
		 * on the thread's slab; works fine by chance,
		 * only because the attribute doesn't exist yet. */
		assert( attr_find( op->ora_e->e_attrs, slap_schema.si_ad_entryTtl ) == NULL );
		attr_merge_one( op->ora_e, slap_schema.si_ad_entryTtl, &bv, &bv );

		expire = slap_get_time() + ttl;
		bv.bv_val = tsbuf;
		bv.bv_len = sizeof( tsbuf );
		slap_timestamp( &expire, &bv );
		assert( attr_find( op->ora_e->e_attrs, ad_entryExpireTimestamp ) == NULL );
		attr_merge_one( op->ora_e, ad_entryExpireTimestamp, &bv, &bv );

		/* if required, install counter callback */
		if ( di->di_max_dynamicObjects > 0) {
			slap_callback	*sc;

			sc = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx );
			sc->sc_cleanup = dds_freeit_cb;
			sc->sc_response = dds_counter_cb;
			sc->sc_private = di;
			sc->sc_next = op->o_callback;

			op->o_callback = sc;
		}
	}

	return SLAP_CB_CONTINUE;
}