Esempio n. 1
0
static int
db_get_pass(void *handle, const char *qpw, const char *key, char **ppass)
{
    struct _dico_ldap_handle *lp = handle;
    LDAPMessage *res, *msg;
    int rc;
    struct berval **values;
    
    res = _dico_ldap_search(lp, lp->user_filter, qpw, key);
    if (!res)
	return 1;

    rc = ldap_count_entries(lp->ldap, res);
    if (rc == 0) {
	dico_log(L_ERR, 0, "not enough entires");
	ldap_msgfree(res);
	return 1;
    }

    msg = ldap_first_entry(lp->ldap, res);
    
    values = ldap_get_values_len(lp->ldap, msg, qpw);
    if (ldap_count_values_len(values) == 0) {
	dico_log(L_ERR, 0, "not enough entires");
	ldap_msgfree(res);
	return 1;
    }
    *ppass = strdup(values[0]->bv_val);
    rc = *ppass == NULL;
    if (rc)
	dico_log(L_ERR, 0, "not enough memory");
    ldap_value_free_len(values);
    ldap_msgfree(res);
    return rc;
}
Esempio n. 2
0
DWORD
_VdcGetAttributeFromEntry(
    LDAP *pLd,
    LDAPMessage* pEntry,
    PSTR pszAttributeName,
    PSTR *ppszAttributeValue
    )
{
    DWORD dwError = 0;
    PSTR pszAttributeValue = NULL;
    BerValue** ppBerValues = NULL;

    ppBerValues = ldap_get_values_len(pLd, pEntry, pszAttributeName);
    if (ppBerValues != NULL && ldap_count_values_len(ppBerValues) > 0)
    {
        dwError = VmDirAllocateStringA(ppBerValues[0][0].bv_val, &pszAttributeValue);
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    *ppszAttributeValue = pszAttributeValue;

cleanup:
    if (ppBerValues)
    {
        ldap_value_free_len(ppBerValues);
        ppBerValues = NULL;
    }

    return dwError;

error:
    VMDIR_SAFE_FREE_STRINGA(pszAttributeValue);
    goto cleanup;
}
Esempio n. 3
0
/*
 * call-seq:
 * entry.get_values(attr)  => Array of String
 * entry.vals(attr)        => Array of String
 * entry[attr]             => Array of String
 *
 * Return an array of all the values belonging to the attribute, +attr+, of
 * the entry.
 */
VALUE
rb_ldap_entry_get_values (VALUE self, VALUE attr)
{
  RB_LDAPENTRY_DATA *edata;
  char *c_attr;
  struct berval **c_vals;
  int i;
  int count;
  VALUE vals;

  GET_LDAPENTRY_DATA (self, edata);
  c_attr = StringValueCStr (attr);

  c_vals = ldap_get_values_len (edata->ldap, edata->msg, c_attr);
  if (c_vals)
    {
      vals = rb_ary_new ();
      count = ldap_count_values_len (c_vals);
      for (i = 0; i < count; i++)
	{
	  VALUE str;
	  str = rb_tainted_str_new (c_vals[i]->bv_val, c_vals[i]->bv_len);
	  rb_ary_push (vals, str);
	}
      ldap_value_free_len (c_vals);
    }
  else
    {
      vals = Qnil;
    }

  return vals;
}
Esempio n. 4
0
PWCHAR kuhl_m_sid_getRootDomainNamingContext(LDAP *ld)
{
	DWORD dwErr;
	PWCHAR rootAttr[] = {L"rootDomainNamingContext", NULL}, ret = NULL;
	PLDAPMessage pMessage = NULL;
	PBERVAL *pBerVal;

	dwErr = ldap_search_s(ld, NULL, LDAP_SCOPE_BASE, L"(dn=RootDSE)", rootAttr, FALSE, &pMessage);
	if(dwErr == LDAP_SUCCESS)
	{
		if(ldap_count_entries(ld, pMessage) == 1)
		{
			if(pBerVal = ldap_get_values_len(ld, pMessage, rootAttr[0]))
			{
				if(ldap_count_values_len(pBerVal) == 1)
					ret = kull_m_string_qad_ansi_c_to_unicode(pBerVal[0]->bv_val, pBerVal[0]->bv_len);
				else PRINT_ERROR(L"ldap_get_values_len is NOT 1\n");
				ldap_value_free_len(pBerVal);
			}
		}
		else PRINT_ERROR(L"ldap_count_entries is NOT 1\n");
	}
	else PRINT_ERROR(L"ldap_search_s 0x%x (%u)\n", dwErr, dwErr);
	if(pMessage)
		ldap_msgfree(pMessage);
	return ret;
}
Esempio n. 5
0
static void set_attributes(lua_State *L, LDAP *ld, LDAPMessage *entry, int tab)
{
  BerElement *ber = NULL;
  BerValue **values;
  char *attr;
  int i, n;

  attr = ldap_first_attribute(ld, entry, &ber);
  while (attr != NULL) {
    values = ldap_get_values_len(ld, entry, attr);
    n = ldap_count_values_len(values);
    if (n == 0) /* no values */
      lua_pushboolean(L, 1);
    else if (n == 1) /* just one value */
      lua_pushlstring(L, values[0]->bv_val, values[0]->bv_len);
    else { /* multiple values */
      lua_newtable(L);
      for (i = 0; i < n; i++) {
        lua_pushlstring(L, values[i]->bv_val, values[i]->bv_len);
        lua_rawseti(L, -2, i+1);
      }
    }
    lua_setfield(L, tab, attr);
    ldap_value_free_len(values);
    ldap_memfree(attr);
    attr = ldap_next_attribute(ld, entry, ber);
  }
  ber_free(ber, 0);
}
Esempio n. 6
0
/*
  add a single set of ldap message values to a ldb_message
*/
static int lldb_add_msg_attr(struct ldb_context *ldb,
			     struct ldb_message *msg, 
			     const char *attr, struct berval **bval)
{
	int count, i;
	struct ldb_message_element *el;

	count = ldap_count_values_len(bval);

	if (count <= 0) {
		return -1;
	}

	el = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
			      msg->num_elements + 1);
	if (!el) {
		errno = ENOMEM;
		return -1;
	}

	msg->elements = el;

	el = &msg->elements[msg->num_elements];

	el->name = talloc_strdup(msg->elements, attr);
	if (!el->name) {
		errno = ENOMEM;
		return -1;
	}
	el->flags = 0;

	el->num_values = 0;
	el->values = talloc_array(msg->elements, struct ldb_val, count);
	if (!el->values) {
		errno = ENOMEM;
		return -1;
	}

	for (i=0;i<count;i++) {
		/* we have to ensure this is null terminated so that
		   ldb_msg_find_attr_as_string() can work */
		el->values[i].data = talloc_size(el->values, bval[i]->bv_len+1);
		if (!el->values[i].data) {
			errno = ENOMEM;
			return -1;
		}
		memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
		el->values[i].data[bval[i]->bv_len] = 0;
		el->values[i].length = bval[i]->bv_len;
		el->num_values++;
	}

	msg->num_elements++;

	return 0;
}
Esempio n. 7
0
static VALUE ldapmessage2obj(LDAP *ld, LDAPMessage *msg)
{
	VALUE obj;
	
	char *dn, *attr;
	BerElement *ber;
	BerValue **values;
	BerValue *value;
	VALUE rdn, attrs, ary, str;
	int length, i;

	obj = rb_class_new_instance(0, NULL, cLDAP_Message);
	
	// Set the DN
	dn = ldap_get_dn(ld, msg);
	rdn = rb_str_new2(dn);
	ldap_memfree(dn);
	rb_iv_set(obj, "@dn", rdn);
	
	// Set the attributes
	attrs = rb_hash_new();
	attr = ldap_first_attribute(ld, msg, &ber);
	do {
		values = ldap_get_values_len(ld, msg, attr);

		if (values == NULL) {
			rldap_raise(rldap_errno_c(obj));
		}

		ary = rb_ary_new();
		length = ldap_count_values_len(values);

		for (i=0; i<length; i++) {
			value = values[i];
			if (value->bv_len == 4 && strncmp(value->bv_val, "TRUE", value->bv_len) == 0)
				rb_ary_push(ary, Qtrue);
			else if (value->bv_len == 5 && strncmp(value->bv_val, "FALSE", value->bv_len) == 0)
				rb_ary_push(ary, Qfalse);
			else {
				str = rb_str_new(value->bv_val, value->bv_len);
				rb_ary_push(ary, str);
			}
		}
		
		rb_hash_aset(attrs, rb_str_new2(attr), ary);

		ldap_value_free_len(values);
		ldap_memfree(attr);
	} while (attr = ldap_next_attribute(ld, msg, ber));

	ber_free(ber, 0);

	rb_iv_set(obj, "@attrs", attrs);

	return obj;
}
Esempio n. 8
0
/***********************************************************************
 *      ldap_count_values_len     (WLDAP32.@)
 *
 * Count the number of values in an array of berval structures.
 *
 * PARAMS
 *  vals  [I] Pointer to an array of berval structures.
 *
 * RETURNS
 *  Success: The number of values counted.
 *  Failure: 0
 *
 * NOTES
 *  Call ldap_count_values_len with the result of a call to
 *  ldap_get_values_len.
 */
ULONG CDECL WLDAP32_ldap_count_values_len( struct WLDAP32_berval **vals )
{
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
#ifdef HAVE_LDAP

    TRACE( "(%p)\n", vals );
    ret = ldap_count_values_len( (struct berval **)vals );

#endif
    return ret;
}
Esempio n. 9
0
	void BuildReply(int res, LDAPRequest *req)
	{
		LDAPResult *ldap_result = req->result = new LDAPResult();
		req->result->type = req->type;

		if (res != LDAP_SUCCESS)
		{
			ldap_result->error = ldap_err2string(res);
			return;
		}

		if (req->message == NULL)
		{
			return;
		}

		/* a search result */

		for (LDAPMessage *cur = ldap_first_message(this->con, req->message); cur; cur = ldap_next_message(this->con, cur))
		{
			LDAPAttributes attributes;

			char *dn = ldap_get_dn(this->con, cur);
			if (dn != NULL)
			{
				attributes["dn"].push_back(dn);
				ldap_memfree(dn);
				dn = NULL;
			}

			BerElement *ber = NULL;

			for (char *attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber))
			{
				berval **vals = ldap_get_values_len(this->con, cur, attr);
				int count = ldap_count_values_len(vals);

				std::vector<Anope::string> attrs;
				for (int j = 0; j < count; ++j)
					attrs.push_back(vals[j]->bv_val);
				attributes[attr] = attrs;

				ldap_value_free_len(vals);
				ldap_memfree(attr);
			}

			if (ber != NULL)
				ber_free(ber, 0);

			ldap_result->messages.push_back(attributes);
		}
	}
Esempio n. 10
0
/*
** Push an attribute value (or a table of values) on top of the stack.
** @param L lua_State.
** @param ld LDAP Connection.
** @param entry Current entry.
** @param attr Name of entry's attribute to get values from.
** @return 1 in case of success.
*/
static int push_values (lua_State *L, LDAP *ld, LDAPMessage *entry, char *attr) {
	int i, n;
	BerValue **vals = ldap_get_values_len (ld, entry, attr);
	n = ldap_count_values_len (vals);
	if (n == 0) /* no values */
		lua_pushboolean (L, 1);
	else if (n == 1) /* just one value */
		lua_pushlstring (L, vals[0]->bv_val, vals[0]->bv_len);
	else { /* Multiple values */
		lua_newtable (L);
		for (i = 0; i < n; i++) {
			lua_pushlstring (L, vals[i]->bv_val, vals[i]->bv_len);
			lua_rawseti (L, -2, i+1);
		}
	}
	ldap_value_free_len (vals);
	return 1;
}
Esempio n. 11
0
static int
db_get_groups(void *handle, const char *qgr, const char *key,
	      dico_list_t *pgroups)
{
    struct _dico_ldap_handle *lp = handle;
    LDAPMessage *res, *msg;
    int rc;
    dico_list_t groups = NULL;
    
    res = _dico_ldap_search(lp, lp->group_filter, qgr, key);
    if (!res)
	return 1;

    rc = ldap_count_entries(lp->ldap, res);
    if (rc == 0) {
	dico_log(L_INFO, 0, "no groups containing %s", key);
	ldap_msgfree(res);
	*pgroups = NULL;
	return 0;
    }

    groups = dico_list_create();
    dico_list_set_free_item(groups, _free_group, NULL);
    *pgroups = groups;

    rc = 0;
    for (msg = ldap_first_entry(lp->ldap, res); msg;
	 msg = ldap_next_entry(lp->ldap, msg)) {
	struct berval **values;
	size_t i, count;
	
	values = ldap_get_values_len(lp->ldap, msg, qgr);
	count = ldap_count_values_len(values);
	for (i = 0; i < count; i++) {
	    char *s = strdup(values[i]->bv_val);
	    dico_list_append(groups, s);
	}
	ldap_value_free_len(values);
    }
    ldap_msgfree(res);
    return rc;
}
Esempio n. 12
0
void LdapSearch::timerEvent( QTimerEvent *e )
{
	LDAPMessage *result = 0;
	LDAP_TIMEVAL t = { 5, 0 };
	int err = ldap_result( d->ldap, d->msg_id, LDAP_MSG_ALL, &t, &result );
	switch( err )
	{
	case LDAP_SUCCESS: //Timeout
		return;
	case LDAP_RES_SEARCH_ENTRY:
	case LDAP_RES_SEARCH_RESULT:
		break;
	default:
		setLastError( tr("Failed to get result"), err );
		killTimer( e->timerId() );
		return;
	}
	killTimer( e->timerId() );

	QList<QSslCertificate> list;
	for( LDAPMessage *entry = ldap_first_entry( d->ldap, result );
		 entry; entry = ldap_next_entry( d->ldap, entry ) )
	{
		BerElement *pos = 0;
		for( char *attr = ldap_first_attribute( d->ldap, entry, &pos );
			 attr; attr = ldap_next_attribute( d->ldap, entry, pos ) )
		{
			if( qstrcmp( attr, "userCertificate;binary" ) == 0 )
			{
				berval **cert = ldap_get_values_len( d->ldap, entry, attr );
				for( ULONG i = 0; i < ldap_count_values_len( cert ); ++i )
					list << QSslCertificate( QByteArray( cert[i]->bv_val, cert[i]->bv_len ), QSsl::Der );
				ldap_value_free_len( cert );
			}
			ldap_memfree( attr );
		}
		ber_free( pos, 0 );
	}
	ldap_msgfree( result );

	Q_EMIT searchResult( list );
}
Esempio n. 13
0
/*
 * load libldap's value data structure into ruby array of string
 */
static VALUE
rb_ldap_entry_load_val(LDAP *ldap, LDAPMessage *msg, char *c_attr)
{
  struct berval **bv;
  VALUE vals;
  int nvals;
  int i;

  bv = ldap_get_values_len(ldap, msg, c_attr);
  if (bv == NULL)
    return Qnil;

  nvals = ldap_count_values_len(bv);
  vals = rb_ary_new2(nvals);
  for (i = 0; i < nvals; i++) {
    rb_ary_push(vals, rb_tainted_str_new(bv[i]->bv_val, bv[i]->bv_len));
  }
  ldap_value_free_len(bv);

  return vals;
}
Esempio n. 14
0
/*
 * This function will look in ldap id the token correspond to the
 * requested user. It will returns 0 for failure and 1 for success.
 *
 * For the moment ldaps is not supported. ldap serve can be on a
 * remote host.
 *
 * You need the following parameters in you pam config:
 * ldapserver=  OR ldap_uri=
 * ldapdn=
 * user_attr=
 * yubi_attr=
 *
 */
static int
authorize_user_token_ldap (struct cfg *cfg,
                           const char *user,
                           const char *token_id)
{
    DBG(("called"));
    int retval = 0;
    int protocol;
#ifdef HAVE_LIBLDAP
    int yubi_attr_prefix_len = 0;
    LDAP *ld = NULL;
    LDAPMessage *result = NULL, *e;
    BerElement *ber;
    char *a;
    char *attrs[2] = {NULL, NULL};

    struct berval **vals;
    int i, rc;

    char *find = NULL;

    if (cfg->user_attr == NULL) {
        DBG (("Trying to look up user to YubiKey mapping in LDAP, but user_attr not set!"));
        return 0;
    }
    if (cfg->yubi_attr == NULL) {
        DBG (("Trying to look up user to YubiKey mapping in LDAP, but yubi_attr not set!"));
        return 0;
    }
    if (cfg->ldapdn == NULL) {
        DBG (("Trying to look up user to YubiKey mapping in LDAP, but ldapdn not set!"));
        return 0;
    }

    /* Get a handle to an LDAP connection. */
    if (cfg->ldap_uri)
    {
        rc = ldap_initialize (&ld, cfg->ldap_uri);
        if (rc != LDAP_SUCCESS)
        {
            DBG (("ldap_init: %s", ldap_err2string (rc)));
            retval = 0;
            goto done;
        }
    }
    else
    {
        if ((ld = ldap_init (cfg->ldapserver, PORT_NUMBER)) == NULL)
        {
            DBG (("ldap_init"));
            retval = 0;
            goto done;
        }
    }

    /* LDAPv2 is historical -- RFC3494. */
    protocol = LDAP_VERSION3;
    ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &protocol);

    /* Bind anonymously to the LDAP server. */
    rc = ldap_simple_bind_s (ld, NULL, NULL);
    if (rc != LDAP_SUCCESS)
    {
        DBG (("ldap_simple_bind_s: %s", ldap_err2string (rc)));
        retval = 0;
        goto done;
    }

    /* Allocation of memory for search strings depending on input size */
    i = (strlen(cfg->user_attr) + strlen(cfg->ldapdn) + strlen(user) + 3) * sizeof(char);
    if ((find = malloc(i)) == NULL) {
        DBG (("Failed allocating %i bytes", i));
        retval = 0;
        goto done;
    }

    sprintf (find, "%s=%s,%s", cfg->user_attr, user, cfg->ldapdn);

    attrs[0] = (char *) cfg->yubi_attr;

    DBG(("LDAP : look up object '%s', ask for attribute '%s'", find, cfg->yubi_attr));

    /* Search for the entry. */
    if ((rc = ldap_search_ext_s (ld, find, LDAP_SCOPE_BASE,
                                 NULL, attrs, 0, NULL, NULL, LDAP_NO_LIMIT,
                                 LDAP_NO_LIMIT, &result)) != LDAP_SUCCESS)
    {
        DBG (("ldap_search_ext_s: %s", ldap_err2string (rc)));

        retval = 0;
        goto done;
    }

    e = ldap_first_entry (ld, result);
    if (e == NULL)
    {
        DBG (("No result from LDAP search"));
    }
    else
    {
        /* Iterate through each returned attribute. */
        for (a = ldap_first_attribute (ld, e, &ber);
                a != NULL; a = ldap_next_attribute (ld, e, ber))
        {
            if ((vals = ldap_get_values_len (ld, e, a)) != NULL)
            {
                DBG(("LDAP : Found %i values - checking if any of them match '%s%s'",
                     ldap_count_values_len(vals),
                     cfg->yubi_attr_prefix ? cfg->yubi_attr_prefix : "",
                     token_id));

                yubi_attr_prefix_len = cfg->yubi_attr_prefix ? strlen(cfg->yubi_attr_prefix) : 0;

                /* Compare each value for the attribute against the token id. */
                for (i = 0; vals[i] != NULL; i++)
                {
                    /* Only values containing this prefix are considered. */
                    if ((!cfg->yubi_attr_prefix || !strncmp (cfg->yubi_attr_prefix, vals[i]->bv_val, yubi_attr_prefix_len)))
                    {
                        if(!strncmp (token_id, vals[i]->bv_val + yubi_attr_prefix_len, strlen (token_id)))
                        {
                            DBG (("Token Found :: %s", vals[i]->bv_val));
                            retval = 1;
                        }
                    }
                }
                ldap_value_free_len (vals);
            }
            ldap_memfree (a);
        }
        if (ber != NULL)
            ber_free (ber, 0);
    }

done:
    if (result != NULL)
        ldap_msgfree (result);
    if (ld != NULL)
        ldap_unbind (ld);

    /* free memory allocated for search strings */
    if (find != NULL)
        free(find);

#else
    DBG (("Trying to use LDAP, but this function is not compiled in pam_yubico!!"));
    DBG (("Install libldap-dev and then recompile pam_yubico."));
#endif
    return retval;
}
Esempio n. 15
0
/** Extract useful information from the rootDSE of the LDAP server
 *
 * @param[in] ctx	to allocate fr_ldap_directory_t in.
 * @param[out] out	where to write pointer to new fr_ldap_directory_t struct.
 * @param[in,out] pconn	connection for querying the directory.
 * @return
 *	- 0 on success.
 *	- 1 if we failed identifying the directory server.
 *	- -1 on error.
 */
int fr_ldap_directory_alloc(TALLOC_CTX *ctx, fr_ldap_directory_t **out, fr_ldap_connection_t **pconn)
{
	static char const	*attrs[] = { "vendorname",
					     "vendorversion",
					     "isGlobalCatalogReady",
					     "objectClass",
					     "orcldirectoryversion",
					     NULL };
	fr_ldap_rcode_t		status;
	int			entry_cnt;
	int			ldap_errno;
	int			i, num;
	int			rcode = 0;
	struct			berval **values = NULL;
	fr_ldap_directory_t	*directory;

	LDAPMessage *result = NULL, *entry;

	*out = NULL;

	directory = talloc_zero(ctx, fr_ldap_directory_t);
	if (!directory) return -2;
	*out = directory;

	directory->type = FR_LDAP_DIRECTORY_UNKNOWN;

	status = fr_ldap_search(&result, NULL, pconn, "", LDAP_SCOPE_BASE, "(objectclass=*)",
				attrs, NULL, NULL);
	switch (status) {
	case LDAP_PROC_SUCCESS:
		break;

	case LDAP_PROC_NO_RESULT:
		WARN("Capability check failed: Can't access rootDSE");
		rcode = 1;
		goto finish;

	default:
		rcode = 1;
		goto finish;
	}

	entry_cnt = ldap_count_entries((*pconn)->handle, result);
	if (entry_cnt != 1) {
		WARN("Capability check failed: Ambiguous result for rootDSE, expected 1 entry, got %i", entry_cnt);
		rcode = 1;
		goto finish;
	}

	entry = ldap_first_entry((*pconn)->handle, result);
	if (!entry) {
		ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);

		WARN("Capability check failed: Failed retrieving entry: %s", ldap_err2string(ldap_errno));
		rcode = 1;
		goto finish;
	}

	values = ldap_get_values_len((*pconn)->handle, entry, "vendorname");
	if (values) {
		directory->vendor_str = fr_ldap_berval_to_string(directory, values[0]);
		INFO("Directory vendor: %s", directory->vendor_str);

		ldap_value_free_len(values);
	}

	values = ldap_get_values_len((*pconn)->handle, entry, "vendorversion");
	if (values) {
		directory->version_str = fr_ldap_berval_to_string(directory, values[0]);
		INFO("Directory version: %s", directory->version_str);

		ldap_value_free_len(values);
	}

	if (directory->vendor_str) {
		if (strcasestr(directory->vendor_str, "International Business Machines")) {
			directory->type = FR_LDAP_DIRECTORY_EDIRECTORY;
		}

		goto found;
	}

	if (directory->version_str) {
		/*
		 *	Novell eDirectory vendorversion contains eDirectory
		 */
		if (strcasestr(directory->version_str, "eDirectory")) {
			directory->type = FR_LDAP_DIRECTORY_EDIRECTORY;
		/*
		 *	Oracle unified directory vendorversion contains Oracle Unified Directory
		 */
		} else if (strcasestr(directory->version_str, "Oracle Unified Directory")) {
			directory->type = FR_LDAP_DIRECTORY_ORACLE_UNIFIED_DIRECTORY;
		/*
		 *	Unbound directory vendorversion contains UnboundID
		 */
		} else if (strcasestr(directory->version_str, "UnboundID")) {
			directory->type = FR_LDAP_DIRECTORY_UNBOUND_ID;
		/*
		 *	NetScape directory venderversion contains Netscape-Directory
		 */
		} else if (strcasestr(directory->version_str, "Netscape-Directory")) {
			directory->type = FR_LDAP_DIRECTORY_NETSCAPE;
		/*
		 *	Siemens AG directory vendorversion contains DirX Directory
		 */
		} else if (strcasestr(directory->version_str, "DirX Directory")) {
			directory->type = FR_LDAP_DIRECTORY_SIEMENS_AG;
		/*
		 *	Sun One Directory vendorversion contains Sun Java
		 */
		} else if (strcasestr(directory->version_str, "Sun Java")) {
			directory->type = FR_LDAP_DIRECTORY_SUN_ONE_DIRECTORY;
		}
		goto found;
	}

	/*
	 *	isGlobalCatalogReady is only present on ActiveDirectory
	 *	instances. AD doesn't provide vendorname or vendorversion
	 */
	values = ldap_get_values_len((*pconn)->handle, entry, "isGlobalCatalogReady");
	if (values) {
		directory->type = FR_LDAP_DIRECTORY_ACTIVE_DIRECTORY;
		ldap_value_free_len(values);
		goto found;
	}

	/*
	 *	OpenLDAP has a special objectClass for its RootDSE
	 */
	values = ldap_get_values_len((*pconn)->handle, entry, "objectClass");
	if (values) {
		num = ldap_count_values_len(values);
		for (i = 0; i < num; i++) {
			if (strncmp("OpenLDAProotDSE", values[i]->bv_val, values[i]->bv_len) == 0) {
				directory->type = FR_LDAP_DIRECTORY_OPENLDAP;
			}
		}
		ldap_value_free_len(values);
		goto found;
	}

	/*
	 *	Oracle Virtual Directory and Oracle Internet Directory
	 */
	values = ldap_get_values_len((*pconn)->handle, entry, "orcldirectoryversion");
	if (values) {
		if (memmem(values[0]->bv_val, values[0]->bv_len, "OID", 3)) {
			directory->type = FR_LDAP_DIRECTORY_ORACLE_INTERNET_DIRECTORY;
		} else if (memmem(values[0]->bv_val, values[0]->bv_len, "OVD", 3)) {
			directory->type = FR_LDAP_DIRECTORY_ORACLE_VIRTUAL_DIRECTORY;
		}
		ldap_value_free_len(values);
	}

found:
	INFO("Directory type: %s", fr_int2str(fr_ldap_directory_type_table, directory->type, "<INVALID>"));

	switch (directory->type) {
	case FR_LDAP_DIRECTORY_ACTIVE_DIRECTORY:
	case FR_LDAP_DIRECTORY_EDIRECTORY:
		directory->cleartext_password = false;
		break;

	default:
		directory->cleartext_password = true;
		break;
	}

finish:
	if (result) ldap_msgfree(result);

	return rcode;
}
Esempio n. 16
0
/** Convert attribute map into valuepairs
 *
 * Use the attribute map built earlier to convert LDAP values into valuepairs and insert them into whichever
 * list they need to go into.
 *
 * This is *NOT* atomic, but there's no condition for which we should error out...
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[in] request Current request.
 * @param[in] handle associated with entry.
 * @param[in] expanded attributes (rhs of map).
 * @param[in] entry to retrieve attributes from.
 * @return
 *	- Number of maps successfully applied.
 *	- -1 on failure.
 */
int rlm_ldap_map_do(const rlm_ldap_t *inst, REQUEST *request, LDAP *handle,
		    rlm_ldap_map_exp_t const *expanded, LDAPMessage *entry)
{
	vp_map_t const 	*map;
	unsigned int		total = 0;
	int			applied = 0;	/* How many maps have been applied to the current request */

	rlm_ldap_result_t	result;
	char const		*name;

	RINDENT();
	for (map = expanded->maps; map != NULL; map = map->next) {
		int ret;

		name = expanded->attrs[total++];

		/*
		 *	Binary safe
		 */
		result.values = ldap_get_values_len(handle, entry, name);
		if (!result.values) {
			RDEBUG3("Attribute \"%s\" not found in LDAP object", name);

			goto next;
		}

		/*
		 *	Find out how many values there are for the
		 *	attribute and extract all of them.
		 */
		result.count = ldap_count_values_len(result.values);

		/*
		 *	If something bad happened, just skip, this is probably
		 *	a case of the dst being incorrect for the current
		 *	request context
		 */
		ret = map_to_request(request, map, rlm_ldap_map_getvalue, &result);
		if (ret == -1) return -1;	/* Fail */

		/*
		 *	How many maps we've processed
		 */
		applied++;

	next:
		ldap_value_free_len(result.values);
	}
	REXDENT();

	/*
	 *	Retrieve any valuepair attributes from the result, these are generic values specifying
	 *	a radius list, operator and value.
	 */
	if (inst->valuepair_attr) {
		struct berval	**values;
		int		count, i;

		values = ldap_get_values_len(handle, entry, inst->valuepair_attr);
		count = ldap_count_values_len(values);

		RINDENT();
		for (i = 0; i < count; i++) {
			vp_map_t *attr;
			char *value;

			value = rlm_ldap_berval_to_string(request, values[i]);
			RDEBUG3("Parsing attribute string '%s'", value);
			if (map_afrom_attr_str(request, &attr, value,
					       REQUEST_CURRENT, PAIR_LIST_REPLY,
					       REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
				RWDEBUG("Failed parsing '%s' value \"%s\" as valuepair (%s), skipping...",
					fr_strerror(), inst->valuepair_attr, value);
				talloc_free(value);
				continue;
			}
			if (map_to_request(request, attr, map_to_vp, NULL) < 0) {
				RWDEBUG("Failed adding \"%s\" to request, skipping...", value);
			} else {
				applied++;
			}
			talloc_free(attr);
			talloc_free(value);
		}
		REXDENT();
		ldap_value_free_len(values);
	}

	return applied;
}
Esempio n. 17
0
static
DWORD
KtLdapQuery(
    LDAP  *pLd,
    PCSTR  pszBaseDn,
    DWORD  dwScope,
    PCSTR  pszFilter,
    PCSTR  pszAttrName,
    PSTR  *ppszAttrVal
    )
{
    DWORD dwError = ERROR_SUCCESS;
    int lderr = LDAP_SUCCESS;
    char *attrs[2] = {
        NULL, // This gets filled in later
        NULL  // This null terminates the list of attributes
    };
    LDAPMessage *res = NULL;
    LDAPMessage *entry = NULL;
    char *attr = NULL;
    struct berval **ppBv = NULL;
    BerElement *ptr = NULL;
    struct timeval timeout = { .tv_sec  = 10,
                               .tv_usec = 0 };
    PSTR pszAttrVal = NULL;

    dwError = LwAllocateString(pszAttrName,
                               &attrs[0]);
    BAIL_ON_LSA_ERROR(dwError);

    lderr = ldap_search_ext_s(pLd,
                              pszBaseDn,
                              dwScope,
                              pszFilter,
                              attrs,
                              0,
                              NULL,
                              NULL,
                              &timeout,
                              0,
                              &res);
    BAIL_ON_LDAP_ERROR(lderr);

    if (ldap_count_entries(pLd, res))
    {
        entry = ldap_first_entry(pLd, res);
        if (entry == NULL)
        {
            dwError = ERROR_DS_GENERIC_ERROR;
            BAIL_ON_LSA_ERROR(dwError);
        }

        attr = ldap_first_attribute(pLd, entry, &ptr);
        if (attr)
        {
            ppBv = ldap_get_values_len(pLd, entry, attr);
            if (ldap_count_values_len(ppBv))
            {
                dwError = LwAllocateMemory(ppBv[0]->bv_len + 1,
                                           OUT_PPVOID(&pszAttrVal));
                BAIL_ON_LSA_ERROR(dwError);

                memcpy(pszAttrVal, ppBv[0]->bv_val, ppBv[0]->bv_len);
            }

            ldap_memfree(attr);
        }

        ldap_msgfree(res);
    }

    *ppszAttrVal = pszAttrVal;

cleanup:
    if (ppBv)
    {
        ldap_value_free_len(ppBv);
    }

    if (ptr != NULL)
    {
        ber_free( ptr, 0 );
    }

    LW_SAFE_FREE_STRING(attrs[0]);

    if (dwError == ERROR_SUCCESS &&
        lderr != LDAP_SUCCESS)
    {
        dwError = LwMapLdapErrorToLwError(lderr);
    }

    return dwError;

error:
    *ppszAttrVal = NULL;

    goto cleanup;
}

static
DWORD
KtLdapUnbind(
    LDAP *pLd
    )
{
    DWORD dwError = ERROR_SUCCESS;
    int lderr = LDAP_SUCCESS;

    lderr = ldap_unbind_ext_s(pLd, NULL, NULL);
    BAIL_ON_LDAP_ERROR(lderr);

cleanup:
    if (lderr)
    {
        dwError = LwMapLdapErrorToLwError(lderr);
    }

    return dwError;

error:
    goto cleanup;
}
Esempio n. 18
0
DWORD
VmDirTestGetAttributeValueString(
    LDAP *pLd,
    PCSTR pBase,
    int ldapScope,
    PCSTR pszFilter,
    PCSTR pszAttribute,
    PSTR *ppszAttributeValue
    )
{
    DWORD dwError = 0;
    PCSTR ppszAttrs[2] = {0};
    LDAPMessage *pResult = NULL;
    BerValue** ppBerValues = NULL;
    PSTR pszAttributeValue = NULL;
    LDAPMessage *pEntry = NULL;

    ppszAttrs[0] = pszAttribute;
    dwError = ldap_search_ext_s(
                pLd,
                pBase,
                ldapScope,
                pszFilter,
                (PSTR*)ppszAttrs,
                0,
                NULL,
                NULL,
                NULL,
                -1,
                &pResult);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (ldap_count_entries(pLd, pResult) != 1)
    {
        BAIL_WITH_VMDIR_ERROR(dwError, ERROR_INVALID_STATE);
    }

    pEntry = ldap_first_entry(pLd, pResult);
    if (!pEntry)
    {
        BAIL_WITH_VMDIR_ERROR(dwError, ERROR_INVALID_STATE);
    }

    ppBerValues = ldap_get_values_len(pLd, pEntry, pszAttribute);
    if (!ppBerValues || (ldap_count_values_len(ppBerValues) != 1))
    {
        BAIL_WITH_VMDIR_ERROR(dwError, ERROR_INVALID_STATE);
    }

    dwError = VmDirAllocateStringA(ppBerValues[0]->bv_val, &pszAttributeValue);
    BAIL_ON_VMDIR_ERROR(dwError);

    *ppszAttributeValue = pszAttributeValue;
    pszAttributeValue = NULL;

cleanup:
    VMDIR_SAFE_FREE_STRINGA(pszAttributeValue);

    if (ppBerValues)
    {
        ldap_value_free_len(ppBerValues);
        ppBerValues = NULL;
    }

    if (pResult)
    {
        ldap_msgfree(pResult);
        pResult = NULL;
    }

    return dwError;

error:
    goto cleanup;
}
Esempio n. 19
0
/** Convert group membership information into attributes
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[in] request Current request.
 * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
 * @param[in] entry retrieved by rlm_ldap_find_user or rlm_ldap_search.
 * @param[in] attr membership attribute to look for in the entry.
 * @return One of the RLM_MODULE_* values.
 */
rlm_rcode_t rlm_ldap_cacheable_userobj(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
				       LDAPMessage *entry, char const *attr)
{
	rlm_rcode_t rcode = RLM_MODULE_OK;

	struct berval **values;
	size_t value_len = 0;
	TALLOC_CTX *value_pool;

	char *group_name[LDAP_MAX_CACHEABLE + 1];
	char **name_p = group_name;

	char *group_dn[LDAP_MAX_CACHEABLE + 1];
	char **dn_p;

	char *name;

	VALUE_PAIR *vp, **vps;
	TALLOC_CTX *ctx;
	vp_cursor_t cursor;

	int is_dn, i, count;

	rad_assert(entry);
	rad_assert(attr);

	/*
	 *	Parse the membership information we got in the initial user query.
	 */
	values = ldap_get_values_len((*pconn)->handle, entry, attr);
	if (!values) {
		RDEBUG2("No cacheable group memberships found in user object");

		return RLM_MODULE_OK;
	}
	count = ldap_count_values_len(values);

	vps = radius_list(request, PAIR_LIST_CONTROL);
	ctx = radius_list_ctx(request, PAIR_LIST_CONTROL);
	fr_cursor_init(&cursor, vps);

	/*
	 *	Avoid allocing buffers for each value.
	 *
	 *	The old code used ldap_get_values, which was likely doing
	 *	a very similar thing internally to produce \0 terminated
	 *	buffers from bervalues.
	 */
	for (i = 0; (i < LDAP_MAX_CACHEABLE) && (i < count); i++) value_len += values[i]->bv_len + 1;
	value_pool = talloc_pool(request, value_len);

	for (i = 0; (i < LDAP_MAX_CACHEABLE) && (i < count); i++) {
		is_dn = rlm_ldap_is_dn(values[i]->bv_val, values[i]->bv_len);

		if (inst->cacheable_group_dn) {
			/*
			 *	The easy case, we're caching DNs and we got a DN.
			 */
			if (is_dn) {
				MEM(vp = pairalloc(ctx, inst->cache_da));
				pairstrncpy(vp, values[i]->bv_val, values[i]->bv_len);
				fr_cursor_insert(&cursor, vp);

				RDEBUG("Added %s with value \"%s\" to control list", inst->cache_da->name,
				       vp->vp_strvalue);
			/*
			 *	We were told to cache DNs but we got a name, we now need to resolve
			 *	this to a DN. Store all the group names in an array so we can do one query.
			 */
			} else {
				*name_p++ = rlm_ldap_berval_to_string(value_pool, values[i]);
			}
		}

		if (inst->cacheable_group_name) {
			/*
			 *	The easy case, we're caching names and we got a name.
			 */
			if (!is_dn) {
				MEM(vp = pairalloc(ctx, inst->cache_da));
				pairstrncpy(vp, values[i]->bv_val, values[i]->bv_len);
				fr_cursor_insert(&cursor, vp);

				RDEBUG("Added control:%s with value \"%s\"", inst->cache_da->name,
				       vp->vp_strvalue);
			/*
			 *	We were told to cache names but we got a DN, we now need to resolve
			 *	this to a name.
			 *	Only Active Directory supports filtering on DN, so we have to search
			 *	for each individual group.
			 */
			} else {
				char *dn;

				dn = rlm_ldap_berval_to_string(value_pool, values[i]);
				rcode = rlm_ldap_group_dn2name(inst, request, pconn, dn, &name);
				talloc_free(dn);
				if (rcode != RLM_MODULE_OK) {
					ldap_value_free_len(values);
					talloc_free(value_pool);

					return rcode;
				}

				MEM(vp = pairalloc(ctx, inst->cache_da));
				pairstrncpy(vp, name, talloc_array_length(name) - 1);
				fr_cursor_insert(&cursor, vp);

				RDEBUG("Added control:%s with value \"%s\"", inst->cache_da->name, name);
				talloc_free(name);
			}
		}
	}
	*name_p = NULL;

	rcode = rlm_ldap_group_name2dn(inst, request, pconn, group_name, group_dn, sizeof(group_dn));

	ldap_value_free_len(values);
	talloc_free(value_pool);

	if (rcode != RLM_MODULE_OK) return rcode;

	dn_p = group_dn;
	while (*dn_p) {
		MEM(vp = pairalloc(ctx, inst->cache_da));
		pairstrcpy(vp, *dn_p);
		fr_cursor_insert(&cursor, vp);

		RDEBUG("Added control:%s with value \"%s\"", inst->cache_da->name, *dn_p);
		ldap_memfree(*dn_p);

		dn_p++;
	}

	return rcode;
}
unsigned long LdapValues::length(void) {
  return ldap_count_values_len(_vals);
}
Esempio n. 21
0
/** Query the LDAP directory to check if a user object is a member of a group
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[in] request Current request.
 * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
 * @param[in] dn of user object.
 * @param[in] check vp containing the group value (name or dn).
 * @return One of the RLM_MODULE_* values.
 */
rlm_rcode_t rlm_ldap_check_userobj_dynamic(ldap_instance_t const *inst, REQUEST *request, ldap_handle_t **pconn,
					   char const *dn, VALUE_PAIR *check)
{
	rlm_rcode_t	rcode = RLM_MODULE_NOTFOUND, ret;
	ldap_rcode_t	status;
	bool		name_is_dn = false, value_is_dn = false;

	LDAPMessage     *result = NULL;
	LDAPMessage     *entry = NULL;
	struct berval	**values = NULL;

	char const	*attrs[] = { inst->userobj_membership_attr, NULL };
	int		i, count, ldap_errno;

	RDEBUG2("Checking user object's %s attributes", inst->userobj_membership_attr);
	RINDENT();
	status = rlm_ldap_search(inst, request, pconn, dn, LDAP_SCOPE_BASE, NULL, attrs, &result);
	REXDENT();
	switch (status) {
	case LDAP_PROC_SUCCESS:
		break;

	case LDAP_PROC_NO_RESULT:
		RDEBUG("Can't check membership attributes, user object not found");

		rcode = RLM_MODULE_NOTFOUND;

		/* FALL-THROUGH */
	default:
		goto finish;
	}

	entry = ldap_first_entry((*pconn)->handle, result);
	if (!entry) {
		ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
		REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));

		rcode = RLM_MODULE_FAIL;

		goto finish;
	}

	values = ldap_get_values_len((*pconn)->handle, entry, inst->userobj_membership_attr);
	if (!values) {
		RDEBUG("No group membership attribute(s) found in user object");

		goto finish;
	}

	/*
	 *	Loop over the list of groups the user is a member of,
	 *	looking for a match.
	 */
	name_is_dn = rlm_ldap_is_dn(check->vp_strvalue, check->vp_length);
	count = ldap_count_values_len(values);
	for (i = 0; i < count; i++) {
		value_is_dn = rlm_ldap_is_dn(values[i]->bv_val, values[i]->bv_len);

		RDEBUG2("Processing %s value \"%.*s\" as a %s", inst->userobj_membership_attr,
			(int)values[i]->bv_len, values[i]->bv_val, value_is_dn ? "DN" : "group name");

		/*
		 *	Both literal group names, do case sensitive comparison
		 */
		if (!name_is_dn && !value_is_dn) {
			if ((check->vp_length == values[i]->bv_len) &&
			    (memcmp(values[i]->bv_val, check->vp_strvalue, values[i]->bv_len) == 0)) {
				RDEBUG("User found in group \"%s\". Comparison between membership: name, check: name",
				       check->vp_strvalue);
				rcode = RLM_MODULE_OK;

				goto finish;
			}

			continue;
		}

		/*
		 *	Both DNs, do case insensitive, binary safe comparison
		 */
		if (name_is_dn && value_is_dn) {
			if (check->vp_length == values[i]->bv_len) {
				int j;

				for (j = 0; j < (int)values[i]->bv_len; j++) {
					if (tolower(values[i]->bv_val[j]) != tolower(check->vp_strvalue[j])) break;
				}
				if (j == (int)values[i]->bv_len) {
					RDEBUG("User found in group DN \"%s\". "
					       "Comparison between membership: dn, check: dn", check->vp_strvalue);
					rcode = RLM_MODULE_OK;

					goto finish;
				}
			}

			continue;
		}

		/*
		 *	If the value is not a DN, and the name we were given is a dn
		 *	convert the value to a DN and do a comparison.
		 */
		if (!value_is_dn && name_is_dn) {
			char *resolved;
			bool eq = false;

			RINDENT();
			ret = rlm_ldap_group_dn2name(inst, request, pconn, check->vp_strvalue, &resolved);
			REXDENT();
			if (ret != RLM_MODULE_OK) {
				rcode = ret;
				goto finish;
			}

			if (((talloc_array_length(resolved) - 1) == values[i]->bv_len) &&
			    (memcmp(values[i]->bv_val, resolved, values[i]->bv_len) == 0)) eq = true;
			talloc_free(resolved);
			if (eq) {
				RDEBUG("User found in group \"%.*s\". Comparison between membership: name, check: name "
				       "(resolved from DN \"%s\")", (int)values[i]->bv_len,
				       values[i]->bv_val, check->vp_strvalue);
				rcode = RLM_MODULE_OK;

				goto finish;
			}

			continue;
		}

		/*
		 *	We have a value which is a DN, and a check item which specifies the name of a group,
		 *	convert the value to a name so we can do a comparison.
		 */
		if (value_is_dn && !name_is_dn) {
			char *resolved;
			char *value;
			bool eq = false;

			value = rlm_ldap_berval_to_string(request, values[i]);
			RINDENT();
			ret = rlm_ldap_group_dn2name(inst, request, pconn, value, &resolved);
			REXDENT();
			talloc_free(value);
			if (ret != RLM_MODULE_OK) {
				rcode = ret;
				goto finish;
			}

			if (((talloc_array_length(resolved) - 1) == check->vp_length) &&
			    (memcmp(check->vp_strvalue, resolved, check->vp_length) == 0)) eq = true;
			talloc_free(resolved);
			if (eq) {
				RDEBUG("User found in group \"%s\". Comparison between membership: name "
				       "(resolved from DN \"%s\"), check: name", check->vp_strvalue, value);
				rcode = RLM_MODULE_OK;

				goto finish;
			}

			continue;
		}
		rad_assert(0);
	}

finish:
	if (values) ldap_value_free_len(values);
	if (result) ldap_msgfree(result);

	return rcode;
}
Esempio n. 22
0
static krb5_error_code
LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
		LDAPMessage * msg, LDAPMod *** pmods)
{
    krb5_error_code ret;
    krb5_boolean is_new_entry;
    char *tmp = NULL;
    LDAPMod **mods = NULL;
    hdb_entry_ex orig;
    unsigned long oflags, nflags;
    int i;

    krb5_boolean is_samba_account = FALSE;
    krb5_boolean is_account = FALSE;
    krb5_boolean is_heimdal_entry = FALSE;
    krb5_boolean is_heimdal_principal = FALSE;

    struct berval **vals;

    *pmods = NULL;

    if (msg != NULL) {

	ret = LDAP_message2entry(context, db, msg, 0, &orig);
	if (ret)
	    goto out;

	is_new_entry = FALSE;

	vals = ldap_get_values_len(HDB2LDAP(db), msg, "objectClass");
	if (vals) {
	    int num_objectclasses = ldap_count_values_len(vals);
	    for (i=0; i < num_objectclasses; i++) {
		if (bervalstrcmp(vals[i], "sambaSamAccount"))
		    is_samba_account = TRUE;
		else if (bervalstrcmp(vals[i], structural_object))
		    is_account = TRUE;
		else if (bervalstrcmp(vals[i], "krb5Principal"))
		    is_heimdal_principal = TRUE;
		else if (bervalstrcmp(vals[i], "krb5KDCEntry"))
		    is_heimdal_entry = TRUE;
	    }
	    ldap_value_free_len(vals);
	}

	/*
	 * If this is just a "account" entry and no other objectclass
	 * is hanging on this entry, it's really a new entry.
	 */
	if (is_samba_account == FALSE && is_heimdal_principal == FALSE &&
	    is_heimdal_entry == FALSE) {
	    if (is_account == TRUE) {
		is_new_entry = TRUE;
	    } else {
		ret = HDB_ERR_NOENTRY;
		goto out;
	    }
	}
    } else
	is_new_entry = TRUE;

    if (is_new_entry) {

	/* to make it perfectly obvious we're depending on
	 * orig being intiialized to zero */
	memset(&orig, 0, sizeof(orig));

	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top");
	if (ret)
	    goto out;

	/* account is the structural object class */
	if (is_account == FALSE) {
	    ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass",
			      structural_object);
	    is_account = TRUE;
	    if (ret)
		goto out;
	}

	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5Principal");
	is_heimdal_principal = TRUE;
	if (ret)
	    goto out;

	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5KDCEntry");
	is_heimdal_entry = TRUE;
	if (ret)
	    goto out;
    }

    if (is_new_entry ||
	krb5_principal_compare(context, ent->entry.principal, orig.entry.principal)
	== FALSE)
    {
	if (is_heimdal_principal || is_heimdal_entry) {

	    ret = krb5_unparse_name(context, ent->entry.principal, &tmp);
	    if (ret)
		goto out;

	    ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE,
			      "krb5PrincipalName", tmp);
	    if (ret) {
		free(tmp);
		goto out;
	    }
	    free(tmp);
	}

	if (is_account || is_samba_account) {
	    ret = krb5_unparse_name_short(context, ent->entry.principal, &tmp);
	    if (ret)
		goto out;
	    ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "uid", tmp);
	    if (ret) {
		free(tmp);
		goto out;
	    }
	    free(tmp);
	}
    }

    if (is_heimdal_entry && (ent->entry.kvno != orig.entry.kvno || is_new_entry)) {
	ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
			    "krb5KeyVersionNumber",
			    ent->entry.kvno);
	if (ret)
	    goto out;
    }

    if (is_heimdal_entry && ent->entry.valid_start) {
	if (orig.entry.valid_end == NULL
	    || (*(ent->entry.valid_start) != *(orig.entry.valid_start))) {
	    ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
					       "krb5ValidStart",
					       ent->entry.valid_start);
	    if (ret)
		goto out;
	}
    }

    if (ent->entry.valid_end) {
 	if (orig.entry.valid_end == NULL || (*(ent->entry.valid_end) != *(orig.entry.valid_end))) {
	    if (is_heimdal_entry) {
		ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
						   "krb5ValidEnd",
						   ent->entry.valid_end);
		if (ret)
		    goto out;
            }
	    if (is_samba_account) {
		ret = LDAP_addmod_integer(context, &mods,  LDAP_MOD_REPLACE,
					  "sambaKickoffTime",
					  *(ent->entry.valid_end));
		if (ret)
		    goto out;
	    }
   	}
    }

    if (ent->entry.pw_end) {
	if (orig.entry.pw_end == NULL || (*(ent->entry.pw_end) != *(orig.entry.pw_end))) {
	    if (is_heimdal_entry) {
		ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
						   "krb5PasswordEnd",
						   ent->entry.pw_end);
		if (ret)
		    goto out;
	    }

	    if (is_samba_account) {
		ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
					  "sambaPwdMustChange",
					  *(ent->entry.pw_end));
		if (ret)
		    goto out;
	    }
	}
    }


#if 0 /* we we have last_pw_change */
    if (is_samba_account && ent->entry.last_pw_change) {
	if (orig.entry.last_pw_change == NULL || (*(ent->entry.last_pw_change) != *(orig.entry.last_pw_change))) {
	    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				      "sambaPwdLastSet",
				      *(ent->entry.last_pw_change));
	    if (ret)
		goto out;
	}
    }
#endif

    if (is_heimdal_entry && ent->entry.max_life) {
	if (orig.entry.max_life == NULL
	    || (*(ent->entry.max_life) != *(orig.entry.max_life))) {

	    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				      "krb5MaxLife",
				      *(ent->entry.max_life));
	    if (ret)
		goto out;
	}
    }

    if (is_heimdal_entry && ent->entry.max_renew) {
	if (orig.entry.max_renew == NULL
	    || (*(ent->entry.max_renew) != *(orig.entry.max_renew))) {

	    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				      "krb5MaxRenew",
				      *(ent->entry.max_renew));
	    if (ret)
		goto out;
	}
    }

    oflags = HDBFlags2int(orig.entry.flags);
    nflags = HDBFlags2int(ent->entry.flags);

    if (is_heimdal_entry && oflags != nflags) {

	ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				  "krb5KDCFlags",
				  nflags);
	if (ret)
	    goto out;
    }

    /* Remove keys if they exists, and then replace keys. */
    if (!is_new_entry && orig.entry.keys.len > 0) {
	vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key");
	if (vals) {
	    ldap_value_free_len(vals);

	    ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5Key", NULL);
	    if (ret)
		goto out;
	}
    }

    for (i = 0; i < ent->entry.keys.len; i++) {

	if (is_samba_account
	    && ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) {
	    char *ntHexPassword;
	    char *nt;
	    time_t now = time(NULL);

	    /* the key might have been 'sealed', but samba passwords
	       are clear in the directory */
	    ret = hdb_unseal_key(context, db, &ent->entry.keys.val[i]);
	    if (ret)
		goto out;

	    nt = ent->entry.keys.val[i].key.keyvalue.data;
	    /* store in ntPassword, not krb5key */
	    ret = hex_encode(nt, 16, &ntHexPassword);
	    if (ret < 0) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret, "hdb-ldap: failed to "
				      "hex encode key");
		goto out;
	    }
	    ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "sambaNTPassword",
			      ntHexPassword);
	    free(ntHexPassword);
	    if (ret)
		goto out;
	    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				      "sambaPwdLastSet", now);
	    if (ret)
		goto out;

	    /* have to kill the LM passwod if it exists */
	    vals = ldap_get_values_len(HDB2LDAP(db), msg, "sambaLMPassword");
	    if (vals) {
		ldap_value_free_len(vals);
		ret = LDAP_addmod(&mods, LDAP_MOD_DELETE,
				  "sambaLMPassword", NULL);
		if (ret)
		    goto out;
	    }

	} else if (is_heimdal_entry) {
	    unsigned char *buf;
	    size_t len, buf_size;

	    ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->entry.keys.val[i], &len, ret);
	    if (ret)
		goto out;
	    if(buf_size != len)
		krb5_abortx(context, "internal error in ASN.1 encoder");

	    /* addmod_len _owns_ the key, doesn't need to copy it */
	    ret = LDAP_addmod_len(&mods, LDAP_MOD_ADD, "krb5Key", buf, len);
	    if (ret)
		goto out;
	}
    }

    if (ent->entry.etypes) {
	int add_krb5EncryptionType = 0;

	/*
	 * Only add/modify krb5EncryptionType if it's a new heimdal
	 * entry or krb5EncryptionType already exists on the entry.
	 */

	if (!is_new_entry) {
	    vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType");
	    if (vals) {
		ldap_value_free_len(vals);
		ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5EncryptionType",
				  NULL);
		if (ret)
		    goto out;
		add_krb5EncryptionType = 1;
	    }
	} else if (is_heimdal_entry)
	    add_krb5EncryptionType = 1;

	if (add_krb5EncryptionType) {
	    for (i = 0; i < ent->entry.etypes->len; i++) {
		if (is_samba_account &&
		    ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5)
		{
		    ;
		} else if (is_heimdal_entry) {
		    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_ADD,
					      "krb5EncryptionType",
					      ent->entry.etypes->val[i]);
		    if (ret)
			goto out;
		}
	    }
	}
    }

    /* for clarity */
    ret = 0;

 out:

    if (ret == 0)
	*pmods = mods;
    else if (mods != NULL) {
	ldap_mods_free(mods, 1);
	*pmods = NULL;
    }

    if (msg)
	hdb_free_entry(context, &orig);

    return ret;
}
Esempio n. 23
0
static void
do_random( char *uri, char *manager, struct berval *passwd,
	char *sbase, int scope, char *filter, char *attr,
	char **srchattrs, int noattrs, int nobind,
	int innerloop, int maxretries, int delay, int force, int chaserefs )
{
	LDAP	*ld = NULL;
	int  	i = 0, do_retry = maxretries;
	char	*attrs[ 2 ];
	int     rc = LDAP_SUCCESS;
	int	version = LDAP_VERSION3;
	int	nvalues = 0;
	char	**values = NULL;
	LDAPMessage *res = NULL, *e = NULL;

	attrs[ 0 ] = attr;
	attrs[ 1 ] = NULL;

	ldap_initialize( &ld, uri );
	if ( ld == NULL ) {
		tester_perror( "ldap_initialize", NULL );
		exit( EXIT_FAILURE );
	}

	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); 
	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
		chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );

	if ( do_retry == maxretries ) {
		fprintf( stderr, "PID=%ld - Search(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n",
				(long) pid, innerloop, sbase, filter, attr );
	}

	if ( nobind == 0 ) {
		rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
		if ( rc != LDAP_SUCCESS ) {
			tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
			switch ( rc ) {
			case LDAP_BUSY:
			case LDAP_UNAVAILABLE:
			/* fallthru */
			default:
				break;
			}
			exit( EXIT_FAILURE );
		}
	}

	rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
		filter, attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res );
	switch ( rc ) {
	case LDAP_SIZELIMIT_EXCEEDED:
	case LDAP_TIMELIMIT_EXCEEDED:
	case LDAP_SUCCESS:
		if ( ldap_count_entries( ld, res ) == 0 ) {
			if ( rc ) {
				tester_ldap_error( ld, "ldap_search_ext_s", NULL );
			}
			break;
		}

		for ( e = ldap_first_entry( ld, res ); e != NULL; e = ldap_next_entry( ld, e ) )
		{
			struct berval **v = ldap_get_values_len( ld, e, attr );

			if ( v != NULL ) {
				int n = ldap_count_values_len( v );
				int j;

				values = realloc( values, ( nvalues + n + 1 )*sizeof( char * ) );
				for ( j = 0; j < n; j++ ) {
					values[ nvalues + j ] = strdup( v[ j ]->bv_val );
				}
				values[ nvalues + j ] = NULL;
				nvalues += n;
				ldap_value_free_len( v );
			}
		}

		ldap_msgfree( res );

		if ( !values ) {
			fprintf( stderr, "  PID=%ld - Search base=\"%s\" filter=\"%s\" got %d values.\n",
				(long) pid, sbase, filter, nvalues );
			exit(EXIT_FAILURE);
		}

		if ( do_retry == maxretries ) {
			fprintf( stderr, "  PID=%ld - Search base=\"%s\" filter=\"%s\" got %d values.\n",
				(long) pid, sbase, filter, nvalues );
		}

		for ( i = 0; i < innerloop; i++ ) {
			char	buf[ BUFSIZ ];
#if 0	/* use high-order bits for better randomness (Numerical Recipes in "C") */
			int	r = rand() % nvalues;
#endif
			int	r = ((double)nvalues)*rand()/(RAND_MAX + 1.0);

			snprintf( buf, sizeof( buf ), "(%s=%s)", attr, values[ r ] );

			do_search( uri, manager, passwd,
				sbase, scope, buf, &ld,
				srchattrs, noattrs, nobind,
				1, maxretries, delay, force, chaserefs );
		}
		break;

	default:
		tester_ldap_error( ld, "ldap_search_ext_s", NULL );
		break;
	}

	fprintf( stderr, "  PID=%ld - Search done (%d).\n", (long) pid, rc );

	if ( ld != NULL ) {
		ldap_unbind_ext( ld, NULL, NULL );
	}
}
Esempio n. 24
0
int ld_ldap2fldex(db_fld_t* fld, LDAP* ldap, LDAPMessage* msg, int init)
{
	int i;
	struct ld_fld* lfld;
	str v;

	if (fld == NULL || msg == NULL) return 0;
	for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
		lfld = DB_GET_PAYLOAD(fld + i);
		if (init) {
			if (fld[i].type == DB_NONE) {
				switch (lfld->syntax) {
					case LD_SYNTAX_STRING:
						fld[i].type = DB_STR;
						break;
					case LD_SYNTAX_INT:
					case LD_SYNTAX_BOOL:
					case LD_SYNTAX_BIT:
						fld[i].type = DB_INT;
						break;
					case LD_SYNTAX_FLOAT:
						fld[i].type = DB_FLOAT;
						break;
						
					case LD_SYNTAX_GENTIME:
						fld[i].type = DB_DATETIME;
						break;
					case LD_SYNTAX_BIN:
						fld[i].type = DB_BITMAP;
						break;
				}

			}
			
			/* free the values of the previous object */
			if (lfld->values) ldap_value_free_len(lfld->values);
			lfld->values = ldap_get_values_len(ldap, msg, lfld->attr.s);
			lfld->index = 0;
			
			if (lfld->values == NULL || lfld->values[0] == NULL) {
				fld[i].flags |= DB_NULL;
				/* index == 0 means no value available */
				lfld->valuesnum = 0;
				if (lfld->client_side_filtering && lfld->filter) {
					int j;
					/* if the all filter conditions requires NULL value then we can accept the record */
					for (j=0; lfld->filter[j]; j++) {
						if (lfld->filter[j]->flags & DB_NULL && lfld->filter[j]->op == DB_EQ) {
							continue;
						}
						return 1; /* get next record */
					}
				}
			} else {
				/* init the number of values */
				fld[i].flags &= ~DB_NULL;
				lfld->valuesnum = ldap_count_values_len(lfld->values);
			
				if ((lfld->valuesnum > 1 || lfld->client_side_filtering) && lfld->filter) {
					
					/* in case of multivalue we must check if value fits in filter criteria.
					   LDAP returns record (having each multivalue) if one particular
					   multivalue fits in filter provided to LDAP search. We need
					   filter out these values manually. It not perfect because 
					   LDAP filtering may be based on different rule/locale than
					   raw (ASCII,...) comparision. 
					
					   We reorder values so we'll have interesting values located from top up to valuesnum at the end.

					   The same algorithm is applied for client side filtering
					   
					 */
					 
					do {
						int passed, j;
						for (j=0, passed = 1; lfld->filter[j] && passed; j++) {
							int op;  /* b0..less, b1..equal, b2..greater, zero..non equal */ 
							op = 0x00;
							if (lfld->filter[j]->flags & DB_NULL) {
								/* always non equal because field is not NULL */
							}
							else {
								
								v.s = lfld->values[lfld->index]->bv_val;
								v.len = lfld->values[lfld->index]->bv_len;
							
								if (ldap_fld2db_fld(fld + i, v) < 0) {
									passed = 0;
									break; /* for loop */
								}
								else {
									db_fld_val_t v;
									int t;
									static char buf[30];
									t = lfld->filter[j]->type;
									/* we need compare value provided in match condition with value returned by LDAP.
									   The match value should be the same type as LDAP value obtained during
									   db_cmd(). We implement some basic conversions.
									 */
									v = lfld->filter[j]->v;
									if (t == DB_CSTR) {
										v.lstr.s = v.cstr;
										v.lstr.len = strlen(v.lstr.s);
										t = DB_STR;
									} 
									switch (fld[i].type) {
										case DB_CSTR:
											fld[i].v.lstr.s = fld[i].v.cstr;
											fld[i].v.lstr.len = strlen(fld[i].v.lstr.s);
											fld[i].type = DB_STR; 
											/* no break */
										case DB_STR:
											
											switch (t) {
												case DB_INT:
													v.lstr.len = snprintf(buf, sizeof(buf)-1, "%d", v.int4);
													v.lstr.s = buf;
													break;
												/* numeric conversion for double/float not supported because of non unique string representation */
												default:
													goto skip_conv;
											}
											break;
										case DB_INT:
											switch (t) {
												case DB_DOUBLE:
													if ((double)(int)v.dbl != (double)v.dbl) 
														goto skip_conv;
													v.int4 = v.dbl;
													break;
												case DB_FLOAT:
													if ((float)(int)v.flt != (float)v.flt) 
														goto skip_conv;
													v.int4 = v.flt;
													break;
												case DB_STR: 
													if (v.lstr.len > 0) {
														char c, *p;
														int n;
														c = v.lstr.s[v.lstr.len];
														v.lstr.s[v.lstr.len] = '\0';
														n = strtol(v.lstr.s, &p, 10);
														v.lstr.s[v.lstr.len] = c;
														if ((*p) != '\0') {
															goto skip_conv;
														}
														v.int4 = n;
													}
													break;
												default:
													goto skip_conv;
											}
											break;
										case DB_FLOAT:
											switch (t) {
												case DB_DOUBLE:
													v.flt = v.dbl;
													break;
												case DB_INT:
													v.flt = v.int4;
													break;
												#ifdef  __USE_ISOC99
												case DB_STR: 
													if (v.lstr.len > 0) {
														char c, *p;
														float n;
														c = v.lstr.s[v.lstr.len];
														v.lstr.s[v.lstr.len] = '\0';
														n = strtof(v.lstr.s, &p);
														v.lstr.s[v.lstr.len] = c;
														if ((*p) != '\0') {
															goto skip_conv;
														}
														v.flt = n;
													}
													break;
												#endif
												default:
													goto skip_conv;
											}
											break;
										case DB_DOUBLE:
											switch (t) {
												case DB_FLOAT:
													v.dbl = v.flt;
													break;
												case DB_INT:
													v.dbl = v.int4;
													break;
												case DB_STR: 
													if (v.lstr.len > 0) {
														char c, *p;
														double n;
														c = v.lstr.s[v.lstr.len];
														v.lstr.s[v.lstr.len] = '\0';
														n = strtod(v.lstr.s, &p);
														v.lstr.s[v.lstr.len] = c;
														if ((*p) != '\0') {
															goto skip_conv;
														}
														v.dbl = n;
													}
													break;
												default:
													goto skip_conv;
											}
											break;
										case DB_BLOB:
										case DB_BITMAP:
										case DB_DATETIME:
										default:
											goto skip_conv;
										}
									t = fld[i].type;
								skip_conv:
									if (t == fld[i].type) {
									
										switch (fld[i].type) {
											case DB_CSTR: /* impossible, already converted to DB_STR */
											case DB_STR:
												if (fld[i].v.lstr.len == v.lstr.len) {
													op = strncmp(fld[i].v.lstr.s, v.lstr.s, v.lstr.len);
													if (op < 0) 
														op = 0x01;
													else if (op > 0)
														op = 0x04;
													else
														op = 0x02;
												}
												else if (fld[i].v.lstr.len < v.lstr.len) {
													op = strncmp(fld[i].v.lstr.s, v.lstr.s, fld[i].v.lstr.len);
													if (op < 0) 
														op = 0x01;
													else 
														op = 0x04;
												}
												else /* if (fld[i].v.lstr.len > v.lstr.len) */ {
													op = strncmp(fld[i].v.lstr.s, v.lstr.s, v.lstr.len);
													if (op > 0) 
														op = 0x04;
													else 
														op = 0x01;
												}
												break;
											case DB_BLOB:
												if (fld[i].v.blob.len == v.blob.len && memcmp(fld[i].v.blob.s, v.blob.s, v.blob.len) == 0)
													op = 0x02;
												break;											
											case DB_INT:
												CMP_NUM(fld[i].v, v, int4);
												break; 
											case DB_BITMAP:
												CMP_NUM(fld[i].v, v, bitmap);
												break; 
											case DB_DATETIME:
												CMP_NUM(fld[i].v, v, time);
												break; 
											case DB_FLOAT:
												CMP_NUM(fld[i].v, v, flt);
												break; 
											case DB_DOUBLE:
												CMP_NUM(fld[i].v, v, dbl);
												break; 
											default:
												;
										}
									}
									 
								}
							}
							switch (lfld->filter[j]->op) {
								case DB_EQ:
									passed = op == 0x02;
									break;
								case DB_NE:
									passed = (op & 0x02) == 0;
									break;
								case DB_LT:
									passed = op == 0x01;
									break;
								case DB_LEQ:
									passed = op == 0x01 || op == 0x02;
									break;
								case DB_GT:
									passed = op == 0x04;
									break;
								case DB_GEQ:
									passed = op == 0x04 || op == 0x02;
									break;
								default:
									;
							}
						}
						
						if (passed) {
							lfld->index++;	
						}
						else {
							char *save_bvval;
							int save_bvlen;
							int i;
							/* shift following values, push useless value at the end and decrease num of values */
							
							save_bvval = lfld->values[lfld->index]->bv_val;
							save_bvlen = lfld->values[lfld->index]->bv_len;
							for (i=lfld->index+1; i < lfld->valuesnum; i++) {
								 lfld->values[i-1]->bv_val = lfld->values[i]->bv_val;
								 lfld->values[i-1]->bv_len = lfld->values[i]->bv_len;
							}
							lfld->values[lfld->valuesnum-1]->bv_val = save_bvval;
							lfld->values[lfld->valuesnum-1]->bv_len = save_bvlen;
							lfld->valuesnum--;
						}
				
					} while (lfld->index < lfld->valuesnum);
						
					if (lfld->valuesnum == 0) {
						return 1;  /* get next record */
					}
				}
			}	
			/* pointer to the current value */
			lfld->index = 0;
		}

		/* this is an empty value */
		if (!lfld->valuesnum)
			continue;

		v.s = lfld->values[lfld->index]->bv_val;
		v.len = lfld->values[lfld->index]->bv_len;

		if (ldap_fld2db_fld(fld + i, v) < 0) 
			return -1;
		
	}
	return 0;
}
Esempio n. 25
0
/*
 * Construct an hdb_entry from a directory entry.
 */
static krb5_error_code
LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
		   hdb_entry * ent)
{
    char *unparsed_name = NULL, *dn = NULL, *ntPasswordIN = NULL;
    char *samba_acct_flags = NULL;
    int ret;
    unsigned long tmp;
    struct berval **keys;
    char **values;
    int tmp_time;

    memset(ent, 0, sizeof(*ent));
    ent->flags = int2HDBFlags(0);

    ret = LDAP_get_string_value(db, msg, "krb5PrincipalName", &unparsed_name);
    if (ret == 0) {
	ret = krb5_parse_name(context, unparsed_name, &ent->principal);
	if (ret)
	    goto out;
    } else {
	ret = LDAP_get_string_value(db, msg, "uid",
				    &unparsed_name);
	if (ret == 0) {
	    ret = krb5_parse_name(context, unparsed_name, &ent->principal);
	    if (ret)
		goto out;
	} else {
	    krb5_set_error_string(context, "hdb-ldap: ldap entry missing"
				  "principal name");
	    return HDB_ERR_NOENTRY;
	}
    }

    ret = LDAP_get_integer_value(db, msg, "krb5KeyVersionNumber",
				 &ent->kvno);
    if (ret)
	ent->kvno = 0;

    keys = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key");
    if (keys != NULL) {
	int i;
	size_t l;

	ent->keys.len = ldap_count_values_len(keys);
	ent->keys.val = (Key *) calloc(ent->keys.len, sizeof(Key));
	if (ent->keys.val == NULL) {
	    krb5_set_error_string(context, "calloc: out of memory");
	    ret = ENOMEM;
	    goto out;
	}
	for (i = 0; i < ent->keys.len; i++) {
	    decode_Key((unsigned char *) keys[i]->bv_val,
		       (size_t) keys[i]->bv_len, &ent->keys.val[i], &l);
	}
	ber_bvecfree(keys);
    } else {
#if 1
	/*
	 * This violates the ASN1 but it allows a principal to
	 * be related to a general directory entry without creating
	 * the keys. Hopefully it's OK.
	 */
	ent->keys.len = 0;
	ent->keys.val = NULL;
#else
	ret = HDB_ERR_NOENTRY;
	goto out;
#endif
    }

    values = ldap_get_values(HDB2LDAP(db), msg, "krb5EncryptionType");
    if (values != NULL) {
	int i;

	ent->etypes = malloc(sizeof(*(ent->etypes)));
	if (ent->etypes == NULL) {
	    krb5_set_error_string(context, "malloc: out of memory");
	    ret = ENOMEM;
	    goto out;
	}
	ent->etypes->len = ldap_count_values(values);
	ent->etypes->val = calloc(ent->etypes->len, sizeof(int));
	if (ent->etypes->val == NULL) {
	    krb5_set_error_string(context, "malloc: out of memory");
	    ret = ENOMEM;
	    goto out;
	}
	for (i = 0; i < ent->etypes->len; i++) {
	    ent->etypes->val[i] = atoi(values[i]);
	}
	ldap_value_free(values);
    }

    /* manually construct the NT (type 23) key */
    ret = LDAP_get_string_value(db, msg, "sambaNTPassword", &ntPasswordIN);
    if (ret == 0) {
	int *etypes;
	Key *keys;

	keys = realloc(ent->keys.val,
		       (ent->keys.len + 1) * sizeof(ent->keys.val[0]));
	if (keys == NULL) {
	    free(ntPasswordIN);
	    krb5_set_error_string(context, "malloc: out of memory");
	    ret = ENOMEM;
	    goto out;
	}
	ent->keys.val = keys;
	memset(&ent->keys.val[ent->keys.len], 0, sizeof(Key));
	ent->keys.val[ent->keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5;
	ret = krb5_data_alloc (&ent->keys.val[ent->keys.len].key.keyvalue, 16);
	if (ret) {
	    krb5_set_error_string(context, "malloc: out of memory");
	    free(ntPasswordIN);
	    ret = ENOMEM;
	    goto out;
	}
	ret = hex_decode(ntPasswordIN,
			 ent->keys.val[ent->keys.len].key.keyvalue.data, 16);
	ent->keys.len++;

	if (ent->etypes == NULL) {
	    ent->etypes = malloc(sizeof(*(ent->etypes)));
	    if (ent->etypes == NULL) {
		krb5_set_error_string(context, "malloc: out of memory");
		ret = ENOMEM;
		goto out;
	    }
	    ent->etypes->val = NULL;
	    ent->etypes->len = 0;
	}

	etypes = realloc(ent->etypes->val, 
			 (ent->etypes->len + 1) * sizeof(ent->etypes->val[0]));
	if (etypes == NULL) {
	    krb5_set_error_string(context, "malloc: out of memory");
	    ret = ENOMEM;
	    goto out;			    
	}
	ent->etypes->val = etypes;
	ent->etypes->val[ent->etypes->len] = ETYPE_ARCFOUR_HMAC_MD5;
	ent->etypes->len++;
    }

    ret = LDAP_get_generalized_time_value(db, msg, "createTimestamp",
					  &ent->created_by.time);
    if (ret)
	ent->created_by.time = time(NULL);

    ent->created_by.principal = NULL;

    ret = LDAP_get_string_value(db, msg, "creatorsName", &dn);
    if (ret == 0) {
	if (LDAP_dn2principal(context, db, dn, &ent->created_by.principal)
	    != 0) {
	    ent->created_by.principal = NULL;
	}
	free(dn);
    }

    ent->modified_by = (Event *) malloc(sizeof(Event));
    if (ent->modified_by == NULL) {
	krb5_set_error_string(context, "malloc: out of memory");
	ret = ENOMEM;
	goto out;
    }
    ret = LDAP_get_generalized_time_value(db, msg, "modifyTimestamp",
					  &ent->modified_by->time);
    if (ret == 0) {
	ret = LDAP_get_string_value(db, msg, "modifiersName", &dn);
	if (LDAP_dn2principal(context, db, dn, &ent->modified_by->principal))
	    ent->modified_by->principal = NULL;
	free(dn);
    } else {
	free(ent->modified_by);
	ent->modified_by = NULL;
    }

    ent->valid_start = malloc(sizeof(*ent->valid_start));
    if (ent->valid_start == NULL) {
	krb5_set_error_string(context, "malloc: out of memory");
	ret = ENOMEM;
	goto out;
    }
    ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidStart",
					  ent->valid_start);
    if (ret) {
	/* OPTIONAL */
	free(ent->valid_start);
	ent->valid_start = NULL;
    }
    
    ent->valid_end = malloc(sizeof(*ent->valid_end));
    if (ent->valid_end == NULL) {
	krb5_set_error_string(context, "malloc: out of memory");
	ret = ENOMEM;
	goto out;
    }
    ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidEnd",
					  ent->valid_end);
    if (ret) {
	/* OPTIONAL */
	free(ent->valid_end);
	ent->valid_end = NULL;
    }

    ret = LDAP_get_integer_value(db, msg, "sambaKickoffTime", &tmp_time);
    if (ret == 0) {
 	if (ent->valid_end == NULL) {
 	    ent->valid_end = malloc(sizeof(*ent->valid_end));
 	    if (ent->valid_end == NULL) {
 		krb5_set_error_string(context, "malloc: out of memory");
 		ret = ENOMEM;
 		goto out;
 	    }
 	}
 	*ent->valid_end = tmp_time;
    }

    ent->pw_end = malloc(sizeof(*ent->pw_end));
    if (ent->pw_end == NULL) {
	krb5_set_error_string(context, "malloc: out of memory");
	ret = ENOMEM;
	goto out;
    }
    ret = LDAP_get_generalized_time_value(db, msg, "krb5PasswordEnd",
					  ent->pw_end);
    if (ret) {
	/* OPTIONAL */
	free(ent->pw_end);
	ent->pw_end = NULL;
    }

    ret = LDAP_get_integer_value(db, msg, "sambaPwdMustChange", &tmp_time);
    if (ret == 0) {
	if (ent->pw_end == NULL) {
	    ent->pw_end = malloc(sizeof(*ent->pw_end));
	    if (ent->pw_end == NULL) {
		krb5_set_error_string(context, "malloc: out of memory");
		ret = ENOMEM;
		goto out;
	    }
	}
	*ent->pw_end = tmp_time;
    }

#if 0 /* we we have last_pw_change */
    ent->last_pw_change = malloc(sizeof(*ent->last_pw_change));
    if (ent->last_pw_change == NULL) {
	krb5_set_error_string(context, "malloc: out of memory");
	ret = ENOMEM;
	goto out;
    }
    ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet",
				 &tmp_time);
    if (ret) {
	/* OPTIONAL */
	free(ent->last_pw_change);
	ent->last_pw_change = NULL;
    } else
	*ent->last_pw_change = tmp_time;
#endif

    ent->max_life = malloc(sizeof(*ent->max_life));
    if (ent->max_life == NULL) {
	krb5_set_error_string(context, "malloc: out of memory");
	ret = ENOMEM;
	goto out;
    }
    ret = LDAP_get_integer_value(db, msg, "krb5MaxLife", ent->max_life);
    if (ret) {
	free(ent->max_life);
	ent->max_life = NULL;
    }

    ent->max_renew = malloc(sizeof(*ent->max_renew));
    if (ent->max_renew == NULL) {
	krb5_set_error_string(context, "malloc: out of memory");
	ret = ENOMEM;
	goto out;
    }
    ret = LDAP_get_integer_value(db, msg, "krb5MaxRenew", ent->max_renew);
    if (ret) {
	free(ent->max_renew);
	ent->max_renew = NULL;
    }

    values = ldap_get_values(HDB2LDAP(db), msg, "krb5KDCFlags");
    if (values != NULL) {
	errno = 0;
	tmp = strtoul(values[0], (char **) NULL, 10);
	if (tmp == ULONG_MAX && errno == ERANGE) {
	    krb5_set_error_string(context, "strtoul: could not convert flag");
	    ret = ERANGE;
	    goto out;
	}
    } else {
	tmp = 0;
    }

    ent->flags = int2HDBFlags(tmp);

    /* Try and find Samba flags to put into the mix */
    ret = LDAP_get_string_value(db, msg, "sambaAcctFlags", &samba_acct_flags);
    if (ret == 0) {
	/* parse the [UXW...] string:
	       
	'N'    No password	 
	'D'    Disabled	 
	'H'    Homedir required	 
	'T'    Temp account.	 
	'U'    User account (normal) 	 
	'M'    MNS logon user account - what is this ? 	 
	'W'    Workstation account	 
	'S'    Server account 	 
	'L'    Locked account	 
	'X'    No Xpiry on password 	 
	'I'    Interdomain trust account	 
	    
	*/	 
	    
	int i;
	int flags_len = strlen(samba_acct_flags);

	if (flags_len < 2)
	    goto out2;

	if (samba_acct_flags[0] != '[' 
	    || samba_acct_flags[flags_len - 1] != ']') 
	    goto out2;

	/* Allow forwarding */
	if (samba_forwardable)
	    ent->flags.forwardable = TRUE;

	for (i=0; i < flags_len; i++) {
	    switch (samba_acct_flags[i]) {
	    case ' ':
	    case '[':
	    case ']':
		break;
	    case 'N':
		/* how to handle no password in kerberos? */
		break;
	    case 'D':
		ent->flags.invalid = TRUE;
		break;
	    case 'H':
		break;
	    case 'T':
		/* temp duplicate */
		ent->flags.invalid = TRUE;
		break;
	    case 'U':
		ent->flags.client = TRUE;
		break;
	    case 'M':
		break;
	    case 'W':
	    case 'S':
		ent->flags.server = TRUE;
		ent->flags.client = TRUE;
		break;
	    case 'L':
		ent->flags.invalid = TRUE;
		break;
	    case 'X':
		if (ent->pw_end) {
		    free(ent->pw_end);
		    ent->pw_end = NULL;
		}
		break;
	    case 'I':
		ent->flags.server = TRUE;
		ent->flags.client = TRUE;
		break;
	    }
	}
    out2:
	free(samba_acct_flags);
    }

    ret = 0;

 out:
    if (unparsed_name)
	free(unparsed_name);

    if (ret)
	hdb_free_entry(context, ent);

    return ret;
}
Esempio n. 26
0
STDMETHODIMP CLDAPQuery::nextResults(
	/* [in] */ LONG results_id,
	/* [in] */ ULONG num_results,
	/* [retval][out] */ SAFEARRAY** result)
{
	CComSafeArray<VARIANT> dnList(0UL);

	ÑConnectInfo *cinfo = NULL;
	ÑResultsInfo *presinfo = NULL;
	m_errorCode = 0L;
	for(int i = 0; i < m_connections.GetSize(); i++)
	{
		ÑConnectInfo * const currentConnectInfo = m_connections.GetValueAt(i);
		if(currentConnectInfo)
		{
			ÑResultsInfo * const resInfo = currentConnectInfo->findResult(results_id);
			if(resInfo)
			{
				cinfo = currentConnectInfo;
				presinfo = resInfo;
				break;
			}
		}
	}
	if(cinfo && presinfo && presinfo->pages())
	{
		const PLDAP ld = cinfo->ld();
		const PLDAPSearch pPages = presinfo->pages();
		PLDAPMessage pMsg = NULL;
		const BOOL allResults = (num_results == 0UL);
		while((allResults || num_results > 0UL) &&
			(m_errorCode = ldap_get_next_page_s(ld, pPages, NULL, (num_results < 1000UL && num_results > 0UL ? num_results : 1000UL), NULL, &pMsg)) == LDAP_SUCCESS) //not more the 1k results per query
		{
			if(pMsg)
			{
				for(PLDAPMessage entry = ldap_first_entry(ld, pMsg); entry != NULL && (allResults || num_results-- > 0UL); entry = ldap_next_entry(ld, entry))
				{
					CComObject<CAssocObject> *obj;
					CComObject<CAssocObject>::CreateInstance(&obj);

					const PTCHAR dn = ldap_get_dn(ld, entry);
					obj->AddValue(_T("dn"), CComVariant(dn));

					PTCHAR attr;
					BerElement* berElem = NULL;
					for(attr = ldap_first_attribute(ld, entry, &berElem); attr != NULL; attr = ldap_next_attribute(ld, entry, berElem))
					{
						bool single = false;
						const AttrSchema* const schema = cinfo->attrSchemaLookup(attr);
						if(schema)
						{
							single = schema->single;
							if(schema->type == OctetString) //we need to work different only with binary data
							{
								PBERVAL *vals;
								if((vals = ldap_get_values_len(ld, entry, attr)) != NULL)
								{
									if(!single)
									{
										CComSafeArray<VARIANT> attrValues(ldap_count_values_len(vals));
										for(LONG i = 0L; vals[i] != NULL; i++)
										{
											attrValues[i] = CAttributesSchema::getAttributeVariant(vals[i], schema->type);
										}
										obj->AddValue(attr, CComVariant(attrValues));
									}
									else
									{
										obj->AddValue(attr, CAttributesSchema::getAttributeVariant(vals[0], schema->type));
									}
									ldap_value_free_len(vals);
								}
								ldap_memfree(attr);
								continue;
							}
						}
						PTCHAR *vals;
						if((vals = ldap_get_values(ld, entry, attr)) != NULL && ldap_count_values(vals) > 0UL)
						{
							if(!single)
							{
								CComSafeArray<VARIANT> attrValues(ldap_count_values(vals));
								for(LONG i = 0L; vals[i] != NULL; i++)
								{
									attrValues[i] = CComVariant(vals[i]);
								}
								obj->AddValue(attr, CComVariant(attrValues));
							}
							else
							{
								obj->AddValue(attr, CComVariant(vals[0]));
							}
							ldap_value_free(vals);
						}
						else
						{
							BOOL last = FALSE;
							LONG start = 0L;
							CComSafeArray<VARIANT> attrValues(0UL);
							do
							{
								CString attrWithRange;
								if(last)
									attrWithRange.Format(_T("%s;range=%ld-*"), attr, start);
								else
									attrWithRange.Format(_T("%s;range=%ld-%ld"), attr, start, start+999L);
								CSimpleArray<PTCHAR> a;
								a.Add(attrWithRange.GetBuffer());
								a.Add(NULL);
								PLDAPMessage pItemMsg = NULL;
								if(ldap_search_s(ld, dn, LDAP_SCOPE_BASE, _T("(objectClass=*)"), a.GetData(), 0, &pItemMsg) == LDAP_SUCCESS)
								{
									PLDAPMessage const itemEntry = ldap_first_entry(ld, pItemMsg);
									if(itemEntry)
									{
										if((vals = ldap_get_values(ld, itemEntry, attrWithRange.GetBuffer())) != NULL)
										{
											if(ldap_count_values(vals) == 0)
											{
												if(last) start = -1L; //leave loop if already last
												last = TRUE;
											}
											else
											{
												for(LONG i = 0L; vals[i] != NULL; i++)
												{
													attrValues.Add(CComVariant(vals[i]));
												}
												if(last) start = -1L; //leave loop
												else start += 1000L; //next results
											}
											ldap_value_free(vals);
										}
										else
										{
											if(last) start = -1L; //leave loop if already last
											last = TRUE;
										}
									}
									else
									{
										start = -1L; //leave loop
									}
									ldap_msgfree(pItemMsg);
								}
								else
								{
									start = -1L; //leave loop
								}
							} while (start >= 0L);
							obj->AddValue(attr, CComVariant(attrValues));
						}
						ldap_memfree(attr);
					}
					dnList.Add(CComVariant(obj));
					ldap_memfree(dn);
				}
				ldap_msgfree(pMsg);
			}
		}
		if(m_errorCode != LDAP_SUCCESS && m_errorCode != LDAP_SIZELIMIT_EXCEEDED)
		{
			cinfo->removeResult(results_id);
		}
		if(m_errorCode == LDAP_NO_RESULTS_RETURNED || m_errorCode == LDAP_MORE_RESULTS_TO_RETURN || m_errorCode == LDAP_SIZELIMIT_EXCEEDED)
			m_errorCode = LDAP_SUCCESS;
	}
	*result = dnList.Detach();
	return S_OK;
}
Esempio n. 27
0
/**
* Get certificate from LDAP-Server.
*/
static int ldap_get_certificate(const char *login) {
	LDAP *ldap_connection;
	int entries;
	LDAPMessage *res;
	LDAPMessage *entry;
	struct berval **bvals = NULL;
	BerElement *ber = NULL;
	char *name = NULL;
	char filter_str[100];
	char *attrs[2];
	int rv = LDAP_SUCCESS;
	void *bv_val;

	char uri[4096];
	char uribuf[4096];
	char *uris[LDAP_CONFIG_URI_MAX + 1];
	const char *p;
	int current_uri = 0, start_uri = 0;

	char *buffer;
	size_t buflen;

	uris[0] = NULL;

	attrs[0] = (char *)attribute;
	attrs[1] = NULL;

	DBG1("ldap_get_certificate(): begin login = %s", login);

	/* Put the login to the %s in Filterstring */
	snprintf(filter_str, sizeof(filter_str), filter, login);

	DBG1("ldap_get_certificate(): filter_str = %s", filter_str);

	/* parse and split URI config entry */
	buffer = uribuf;
	buflen = sizeof (uribuf);

	strncpy(uri, ldapURI, sizeof (uri)-1);

	/* Add a space separated list of URIs */
	/* TODO: no spaces in one URI allowed => URL-encoding? */
	if(strncmp(ldapURI,"",1))
		for (p = uri; p != NULL; )
		{
			char *q = strchr (p, ' ');
			if (q != NULL)
				*q = '\0';

			if( strlen(p) > 1 ) /* SAW: don't add spaces */
				rv = ldap_add_uri (uris, p, &buffer, &buflen);

			p = (q != NULL) ? ++q : NULL;

			if (rv)
				break;
		}
    /* set the default port if no port is given */
  	if (ldapport == 0)
    {
		if (ssl_on == SSL_LDAPS)
		{
		  ldapport = LDAPS_PORT;
		}
		else
		{
		  ldapport = LDAP_PORT;
		}
	}

	/* add ldaphost to uris if set, nevermind "uri" is set in config */
	if( strlen(ldaphost) > 1 )
	{
		/* No port specified in URI and non-default port specified */
		snprintf (uri, sizeof (uri), "%s%s:%d",
		       ssl_on == SSL_LDAPS ? "ldaps://" : "ldap://",
		       ldaphost, ldapport);
		ldap_add_uri (uris, uri, &buffer, &buflen);
	}

  	if (uris[0] == NULL)
    {
		DBG("ldap_get_certificate(): Nor URI or usable Host entry found");
		return(-1);
    }

	/* Attempt to connect to specified URI in order until do_open succeed */
	start_uri = current_uri;
	do
	{
		if(uris[current_uri] != NULL)
			DBG1("ldap_get_certificate(): try do_open for %s", uris[current_uri]);
		rv = do_open(&ldap_connection, uris[current_uri], ldapport, ssl_on);
		/* hot-fix, because in some circumstances an LDAP_SERVER_DOWN is returned */
		if (rv != LDAP_UNAVAILABLE && rv != LDAP_SERVER_DOWN)
			break;
		current_uri++;

		if (uris[current_uri] == NULL)
			current_uri = 0;
	}
	while (current_uri != start_uri);

	if( rv != LDAP_SUCCESS )
	{
		DBG("ldap_get_certificate(): do_open failed");
		return(-2);
	}

	/* TODO: (1) The problem: if an working uri is found it is used
    	     and if there is an (SSL-)error, no other one is tried
    	     (2) There is no session, so we don't know which LDAP_Server
    	     is the last with a successful connection. So we try the same
    	     server again. Perhaps create a state file/smem/etc. ?
    */

	rv = ldap_search_s(
				ldap_connection,
				base,
				sscope[scope],
				filter_str,
				attrs,
				0,
				&res);
	if ( rv != LDAP_SUCCESS ) {
		DBG1("ldap_search_s() failed: %s", ldap_err2string(rv));
		ldap_unbind_s(ldap_connection);
		return(-3);
	} else {
		entries = ldap_count_entries(ldap_connection, res);
		DBG1("ldap_get_certificate(): entries = %d", entries);

		if( entries > 1 ) {
			DBG("!  Warning, more than one entry found. Please choose \"filter\" and");
			DBG("!  \"attribute\" in ldap mapper config section of your config,");
			DBG("!  that only one entry with one attribute is matched");
			DBG("!  Maybe there is another problem in ldap with not unique user");
			DBG("!  entries in your LDAP server.");
		}

		/* Only first entry is used. "filter" and "attribute"
		 *  should be choosen, so that only one entry with
		 * one attribute is returned */
		if ( NULL == (entry = ldap_first_entry(ldap_connection, res))){
			DBG("ldap_first_entry() failed: %s");
			ldap_unbind_s(ldap_connection);
			return(-4);
		}

		/* Only first attribute is used. See comment above... */
		if ( NULL == (name = ldap_first_attribute(ldap_connection, res, &ber))){
			DBG("ldap_first_attribute() failed (rc=%d)");
			ldap_unbind_s(ldap_connection);
			return(-5);
		}
		DBG1("attribute name = %s", name);

		bvals = ldap_get_values_len(ldap_connection, entry, name);
		certcnt = ldap_count_values_len(bvals);

		DBG1("number of user certificates = %d", certcnt);

		ldap_x509 = malloc(sizeof(X509*) * certcnt );
		if (NULL == ldap_x509)
		{
			DBG("not enough memory");
			return(-7);
		}

		rv = 0;
		while(rv < certcnt )
		{
			/* SaW: not nifty, but otherwise gcc doesn't optimize */
			bv_val = &bvals[rv]->bv_val;
#ifdef HAVE_NSS
			{
				SECItem derdata;
				derdata.data = bv_val;
				derdata.len = bvals[rv]->bv_len;

				ldap_x509[rv] = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
					&derdata, NULL, 0, 1);
			}
#else
			ldap_x509[rv] = d2i_X509(NULL, ((const unsigned char **) bv_val), bvals[rv]->bv_len);
#endif
			if (NULL == ldap_x509[rv]) {
				DBG1("d2i_X509() failed for certificate %d", rv);
				free(ldap_x509);
#ifdef HAVE_NSS
				{
					for (rv=0; rv<certcnt; rv++)
						if (ldap_x509[rv])
							CERT_DestroyCertificate(ldap_x509[rv]);
				}
#endif
				certcnt=0;
				ldap_msgfree(res);
				ldap_unbind_s(ldap_connection);
				return(-6);
			}else {
				DBG1("d2i_X509(): success for certificate %d", rv);
			}
			rv++;
		}
		ldap_msgfree(res);
		/* TODO: this leads to a segfault, but the doc said ... */
		/* ldap_value_free_len(bvals); */
	}
	if ( 0 != ldap_unbind_s(ldap_connection)) {
		DBG("ldap_unbind_s() failed.");
		ldap_perror(ldap_connection, "ldap_unbind_s() failed.");
		return(-1);
	};

	DBG("ldap_get_certificate(): end");
	return 1;
}
Esempio n. 28
0
DWORD
VdcLdapGetAttributeValue(
    LDAP *pLd,
    PCSTR pszObjectDN,
    PCSTR pszAttribute,
    PSTR *ppszAttributeValue
    )
{
    DWORD dwError = 0;
    PCSTR ppszAttrs[2] = {0};
    LDAPMessage *pResult = NULL;
    BerValue** ppBerValues = NULL;
    PSTR pszAttributeValue = NULL;

    ppszAttrs[0] = pszAttribute;
    dwError = ldap_search_ext_s(
                pLd,
                pszObjectDN,
                LDAP_SCOPE_BASE,
                "(objectClass=*)",
                (PSTR*)ppszAttrs,
                0,
                NULL,
                NULL,
                NULL,
                -1,
                &pResult);

    if (ldap_count_entries(pLd, pResult) > 0)
    {
        LDAPMessage* pEntry = ldap_first_entry(pLd, pResult);

        for (; pEntry != NULL; pEntry = ldap_next_entry(pLd, pEntry))
        {
            BerValue** ppBerValues = NULL;
            ppBerValues = ldap_get_values_len(pLd, pEntry, pszAttribute);
            if (ppBerValues != NULL && ldap_count_values_len(ppBerValues) > 0)
            {
                dwError = VmDirAllocateStringA(
                            ppBerValues[0][0].bv_val,
                            &pszAttributeValue);
                BAIL_ON_VMDIR_ERROR(dwError);
                break;
            }
        }
    }

    *ppszAttributeValue = pszAttributeValue;

cleanup:

    if (ppBerValues)
    {
        ldap_value_free_len(ppBerValues);
        ppBerValues = NULL;
    }

    if (pResult)
    {
        ldap_msgfree(pResult);
        pResult = NULL;
    }

    return dwError;

error:

    VMDIR_SAFE_FREE_STRINGA(pszAttributeValue);
    goto cleanup;
}
Esempio n. 29
0
// wrapper for get_values_len
//
NS_IMETHODIMP 
nsLDAPMessage::GetBinaryValues(const char *aAttr, PRUint32 *aCount,
                               nsILDAPBERValue ***aValues)
{
    struct berval **values;

#if defined(DEBUG)
    // We only want this being logged for debug builds so as not to affect performance too much.
    PR_LOG(gLDAPLogModule, PR_LOG_DEBUG,
           ("nsLDAPMessage::GetBinaryValues(): called with aAttr = '%s'", 
            aAttr));
#endif

    values = ldap_get_values_len(mConnectionHandle, mMsgHandle, aAttr);

    // bail out if there was a problem
    //
    if (!values) {
        PRInt32 lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);

        if ( lderrno == LDAP_DECODING_ERROR ) {
            // this may not be an error; it could just be that the 
            // caller has asked for an attribute that doesn't exist.
            //
            PR_LOG(gLDAPLogModule, PR_LOG_WARNING, 
                   ("nsLDAPMessage::GetBinaryValues(): ldap_get_values "
                    "returned LDAP_DECODING_ERROR"));
            return NS_ERROR_LDAP_DECODING_ERROR;

        } else if ( lderrno == LDAP_PARAM_ERROR ) {
            NS_ERROR("nsLDAPMessage::GetBinaryValues(): internal error: 1");
            return NS_ERROR_UNEXPECTED;

        } else {
            NS_ERROR("nsLDAPMessage::GetBinaryValues(): internal error: 2");
            return NS_ERROR_UNEXPECTED;
        }
    }

    // count the values
    //
    PRUint32 numVals = ldap_count_values_len(values);

    // create the out array
    //
    *aValues = 
        static_cast<nsILDAPBERValue **>(nsMemory::Alloc(numVals * sizeof(nsILDAPBERValue)));
    if (!aValues) {
        ldap_value_free_len(values);
        return NS_ERROR_OUT_OF_MEMORY;
    }

    // clone the array (except for the trailing NULL entry) using the 
    // shared allocator for XPCOM correctness
    //
    PRUint32 i;
    nsresult rv;
    for ( i = 0 ; i < numVals ; i++ ) {

        // create an nsBERValue object
        //
        nsCOMPtr<nsILDAPBERValue> berValue = new nsLDAPBERValue();
        if (!berValue) {
            NS_ERROR("nsLDAPMessage::GetBinaryValues(): out of memory"
                     " creating nsLDAPBERValue object");
            NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, aValues);
            ldap_value_free_len(values);
            return NS_ERROR_OUT_OF_MEMORY;
        }

        // copy the value from the struct into the nsBERValue
        //
        rv = berValue->Set(values[i]->bv_len, 
                           reinterpret_cast<PRUint8 *>(values[i]->bv_val));
        if (NS_FAILED(rv)) {
            NS_ERROR("nsLDAPMessage::GetBinaryValues(): error setting"
                     " nsBERValue");
            ldap_value_free_len(values);
            return rv == NS_ERROR_OUT_OF_MEMORY ? rv : NS_ERROR_UNEXPECTED;
        }

        // put the nsIBERValue object into the out array
        //
        NS_ADDREF( (*aValues)[i] = berValue.get() );
    }

    *aCount = numVals;
    ldap_value_free_len(values);
    return NS_OK;
}
Esempio n. 30
0
DWORD
VmDirTestGetAttributeValue(
    LDAP *pLd,
    PCSTR pBase,
    int ldapScope,
    PCSTR pszFilter,
    PCSTR pszAttribute,
    BYTE **ppbAttributeValue,
    PDWORD pdwAttributeLength
    )
{
    DWORD dwError = 0;
    PCSTR ppszAttrs[2] = {0};
    LDAPMessage *pResult = NULL;
    BerValue** ppBerValues = NULL;
    BYTE *pbAttributeValue = NULL;
    DWORD dwAttributeLength = 0;

    ppszAttrs[0] = pszAttribute;
    dwError = ldap_search_ext_s(
                pLd,
                pBase,
                ldapScope,
                pszFilter ? pszFilter : "",
                (PSTR*)ppszAttrs,
                0,
                NULL,
                NULL,
                NULL,
                -1,
                &pResult);
    BAIL_ON_VMDIR_ERROR(dwError);

    if (ldap_count_entries(pLd, pResult) > 0)
    {
        LDAPMessage* pEntry = ldap_first_entry(pLd, pResult);

        for (; pEntry != NULL; pEntry = ldap_next_entry(pLd, pEntry))
        {
            BerValue** ppBerValues = NULL;
            ppBerValues = ldap_get_values_len(pLd, pEntry, pszAttribute);
            if (ppBerValues != NULL && ldap_count_values_len(ppBerValues) > 0)
            {
                dwError = VmDirAllocateAndCopyMemory(
                            ppBerValues[0][0].bv_val,
                            ppBerValues[0][0].bv_len,
                            (PVOID*)&pbAttributeValue);
                BAIL_ON_VMDIR_ERROR(dwError);

                dwAttributeLength = ppBerValues[0][0].bv_len;
                break;
            }
        }
    }

    *ppbAttributeValue = pbAttributeValue;
    *pdwAttributeLength = dwAttributeLength;
    pbAttributeValue = NULL;

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pbAttributeValue);

    if (ppBerValues)
    {
        ldap_value_free_len(ppBerValues);
        ppBerValues = NULL;
    }

    if (pResult)
    {
        ldap_msgfree(pResult);
        pResult = NULL;
    }

    return dwError;

error:
    goto cleanup;
}