Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Joe Martin
OpenLDAP
Commits
317d6587
Commit
317d6587
authored
Jul 09, 1999
by
Kurt Zeilenga
Browse files
Add additional args to send_ldap_result calls.
parent
938fb975
Changes
37
Hide whitespace changes
Inline
Side-by-side
servers/slapd/back-bdb2/add.c
0 → 100644
View file @
317d6587
/* add.c - ldap bdb2 back-end add routine */
#include
"portable.h"
#include
<stdio.h>
#include
<ac/socket.h>
#include
<ac/string.h>
#include
"slap.h"
#include
"back-bdb2.h"
#include
"proto-back-bdb2.h"
static
DB_LOCK
lock
;
static
int
bdb2i_back_add_internal
(
BackendDB
*
be
,
Connection
*
conn
,
Operation
*
op
,
Entry
*
e
)
{
struct
ldbminfo
*
li
=
(
struct
ldbminfo
*
)
be
->
be_private
;
char
*
pdn
;
Entry
*
p
=
NULL
;
int
rc
;
struct
timeval
time1
;
Debug
(
LDAP_DEBUG_ARGS
,
"==> bdb2i_back_add: %s
\n
"
,
e
->
e_dn
,
0
,
0
);
if
(
(
bdb2i_dn2id
(
be
,
e
->
e_ndn
)
)
!=
NOID
)
{
entry_free
(
e
);
send_ldap_result
(
conn
,
op
,
LDAP_ALREADY_EXISTS
,
NULL
,
NULL
,
NULL
);
return
(
-
1
);
}
if
(
global_schemacheck
&&
oc_schema_check
(
e
)
!=
0
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"entry failed schema check
\n
"
,
0
,
0
,
0
);
entry_free
(
e
);
send_ldap_result
(
conn
,
op
,
LDAP_OBJECT_CLASS_VIOLATION
,
NULL
,
NULL
,
NULL
);
return
(
-
1
);
}
/*
* Get the parent dn and see if the corresponding entry exists.
* If the parent does not exist, only allow the "root" user to
* add the entry.
*/
pdn
=
dn_parent
(
be
,
e
->
e_ndn
);
if
(
pdn
!=
NULL
&&
*
pdn
!=
'\0'
&&
!
be_issuffix
(
be
,
""
)
)
{
char
*
matched
=
NULL
;
assert
(
*
pdn
!=
'\0'
);
/* get parent with writer lock */
if
(
(
p
=
bdb2i_dn2entry_w
(
be
,
pdn
,
&
matched
))
==
NULL
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"parent does not exist
\n
"
,
0
,
0
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_NO_SUCH_OBJECT
,
matched
,
NULL
,
NULL
);
if
(
matched
!=
NULL
)
{
free
(
matched
);
}
entry_free
(
e
);
free
(
pdn
);
return
-
1
;
}
free
(
pdn
);
if
(
matched
!=
NULL
)
{
free
(
matched
);
}
if
(
!
access_allowed
(
be
,
conn
,
op
,
p
,
"children"
,
NULL
,
ACL_WRITE
)
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"no access to parent
\n
"
,
0
,
0
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_INSUFFICIENT_ACCESS
,
NULL
,
NULL
,
NULL
);
/* free parent and writer lock */
bdb2i_cache_return_entry_w
(
&
li
->
li_cache
,
p
);
entry_free
(
e
);
return
-
1
;
}
}
else
{
if
(
pdn
!=
NULL
)
{
assert
(
*
pdn
==
'\0'
);
free
(
pdn
);
}
/* no parent, must be adding entry to root */
if
(
!
be_isroot
(
be
,
op
->
o_ndn
)
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"%s add denied
\n
"
,
pdn
==
NULL
?
"suffix"
:
"entry at root"
,
0
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_INSUFFICIENT_ACCESS
,
NULL
,
NULL
,
NULL
);
entry_free
(
e
);
return
-
1
;
}
}
e
->
e_id
=
bdb2i_next_id
(
be
);
/*
* Try to add the entry to the cache, assign it a new dnid.
*/
bdb2i_start_timing
(
be
->
bd_info
,
&
time1
);
rc
=
bdb2i_cache_add_entry_rw
(
&
li
->
li_cache
,
e
,
CACHE_WRITE_LOCK
);
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-CACHE"
,
conn
,
op
);
if
(
rc
!=
0
)
{
if
(
p
!=
NULL
)
{
/* free parent and writer lock */
bdb2i_cache_return_entry_w
(
&
li
->
li_cache
,
p
);
}
Debug
(
LDAP_DEBUG_ANY
,
"cache_add_entry_lock failed
\n
"
,
0
,
0
,
0
);
/* return the id */
bdb2i_next_id_return
(
be
,
e
->
e_id
);
/* free the entry */
entry_free
(
e
);
if
(
rc
>
0
)
{
send_ldap_result
(
conn
,
op
,
LDAP_ALREADY_EXISTS
,
NULL
,
NULL
,
NULL
);
}
else
{
send_ldap_result
(
conn
,
op
,
LDAP_OPERATIONS_ERROR
,
NULL
,
NULL
,
NULL
);
}
return
(
-
1
);
}
rc
=
-
1
;
/*
* add it to the id2children index for the parent
*/
bdb2i_start_timing
(
be
->
bd_info
,
&
time1
);
if
(
bdb2i_id2children_add
(
be
,
p
,
e
)
!=
0
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"bdb2i_id2children_add failed
\n
"
,
0
,
0
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_OPERATIONS_ERROR
,
NULL
,
NULL
,
NULL
);
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-ID2CHILDREN"
,
conn
,
op
);
goto
return_results
;
}
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-ID2CHILDREN"
,
conn
,
op
);
/*
* Add the entry to the attribute indexes, then add it to
* the id2children index, dn2id index, and the id2entry index.
*/
bdb2i_start_timing
(
be
->
bd_info
,
&
time1
);
/* attribute indexes */
if
(
bdb2i_index_add_entry
(
be
,
e
)
!=
0
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"bdb2i_index_add_entry failed
\n
"
,
0
,
0
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_OPERATIONS_ERROR
,
NULL
,
NULL
,
NULL
);
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-INDEX"
,
conn
,
op
);
goto
return_results
;
}
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-INDEX"
,
conn
,
op
);
bdb2i_start_timing
(
be
->
bd_info
,
&
time1
);
/* dn2id index */
if
(
bdb2i_dn2id_add
(
be
,
e
->
e_ndn
,
e
->
e_id
)
!=
0
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"bdb2i_dn2id_add failed
\n
"
,
0
,
0
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_OPERATIONS_ERROR
,
NULL
,
NULL
,
NULL
);
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-DN2ID"
,
conn
,
op
);
goto
return_results
;
}
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-DN2ID"
,
conn
,
op
);
bdb2i_start_timing
(
be
->
bd_info
,
&
time1
);
/* id2entry index */
if
(
bdb2i_id2entry_add
(
be
,
e
)
!=
0
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"bdb2i_id2entry_add failed
\n
"
,
0
,
0
,
0
);
(
void
)
bdb2i_dn2id_delete
(
be
,
e
->
e_ndn
);
send_ldap_result
(
conn
,
op
,
LDAP_OPERATIONS_ERROR
,
NULL
,
NULL
,
NULL
);
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-ID2ENTRY"
,
conn
,
op
);
goto
return_results
;
}
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD-ID2ENTRY"
,
conn
,
op
);
send_ldap_result
(
conn
,
op
,
LDAP_SUCCESS
,
NULL
,
NULL
,
NULL
);
rc
=
0
;
return_results:
;
if
(
p
!=
NULL
)
{
/* free parent and writer lock */
bdb2i_cache_return_entry_w
(
&
li
->
li_cache
,
p
);
}
if
(
rc
)
{
/* free entry and writer lock */
bdb2i_cache_return_entry_w
(
&
li
->
li_cache
,
e
);
}
return
(
rc
);
}
int
bdb2_back_add
(
BackendDB
*
be
,
Connection
*
conn
,
Operation
*
op
,
Entry
*
e
)
{
struct
ldbminfo
*
li
=
(
struct
ldbminfo
*
)
be
->
be_private
;
struct
timeval
time1
;
int
ret
;
bdb2i_start_timing
(
be
->
bd_info
,
&
time1
);
if
(
bdb2i_enter_backend_w
(
&
lock
)
!=
0
)
{
send_ldap_result
(
conn
,
op
,
LDAP_OPERATIONS_ERROR
,
NULL
,
NULL
,
NULL
);
return
(
-
1
);
}
/* check, if a new default attribute index will be created,
in which case we have to open the index file BEFORE TP */
switch
(
slapMode
)
{
case
SLAP_SERVER_MODE
:
case
SLAP_TIMEDSERVER_MODE
:
case
SLAP_TOOL_MODE
:
case
SLAP_TOOLID_MODE
:
bdb2i_check_default_attr_index_add
(
li
,
e
);
break
;
}
ret
=
bdb2i_back_add_internal
(
be
,
conn
,
op
,
e
);
/* if the operation was successful, we will delay the unlock */
if
(
ret
)
(
void
)
bdb2i_leave_backend_w
(
lock
);
bdb2i_stop_timing
(
be
->
bd_info
,
time1
,
"ADD"
,
conn
,
op
);
return
(
ret
);
}
int
bdb2i_release_add_lock
(
void
)
{
(
void
)
bdb2i_leave_backend_w
(
lock
);
return
0
;
}
servers/slapd/back-bdb2/alias.c
0 → 100644
View file @
317d6587
/*
* Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to ITSD, Government of BC. The name of ITSD
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
#include
"portable.h"
#include
<stdio.h>
#include
<ac/string.h>
#include
<ac/socket.h>
#include
"slap.h"
#include
"back-bdb2.h"
#include
"proto-back-bdb2.h"
/*
* given an alias object, dereference it to its end point.
* Entry returned has reader lock or is NULL. Starting entry is not released.
*/
Entry
*
bdb2i_derefAlias_r
(
BackendDB
*
be
,
Connection
*
conn
,
Operation
*
op
,
Entry
*
e
)
{
/* to free cache entries */
struct
ldbminfo
*
li
=
(
struct
ldbminfo
*
)
be
->
be_private
;
Attribute
*
a
;
int
depth
;
char
*
matched
;
Entry
*
origDN
=
e
;
if
(
!
e
)
return
NULL
;
/* be sure we have a starting entry */
Debug
(
LDAP_DEBUG_TRACE
,
"<= checking for alias for dn %s
\n
"
,
e
->
e_dn
,
0
,
0
);
/*
* try to deref fully, up to a maximum depth. If the max depth exceeded
* then send an error
*/
for
(
depth
=
0
;
(
(
a
=
attr_find
(
e
->
e_attrs
,
"aliasedobjectname"
)
)
!=
NULL
)
&&
(
depth
<
be
->
be_maxDerefDepth
);
++
depth
)
{
/*
* make sure there is a defined aliasedobjectname.
* can only have one value so just use first value (0) in the attr list.
*/
if
(
a
->
a_vals
[
0
]
&&
a
->
a_vals
[
0
]
->
bv_val
)
{
char
*
newDN
,
*
oldDN
;
Debug
(
LDAP_DEBUG_TRACE
,
"<= %s is an alias for %s
\n
"
,
e
->
e_dn
,
a
->
a_vals
[
0
]
->
bv_val
,
0
);
newDN
=
ch_strdup
(
a
->
a_vals
[
0
]
->
bv_val
);
oldDN
=
ch_strdup
(
e
->
e_ndn
);
/*
* release past lock if not original
*/
if
(
(
depth
>
0
)
&&
e
)
{
bdb2i_cache_return_entry_r
(
&
li
->
li_cache
,
e
);
}
/* make sure new and old DN are not same to avoid loops */
dn_normalize_case
(
newDN
);
if
(
strcmp
(
newDN
,
oldDN
)
==
0
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"<= %s alias is same as current %s
\n
"
,
oldDN
,
newDN
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_ALIAS_DEREF_PROBLEM
,
NULL
,
"circular alias"
,
NULL
);
free
(
newDN
);
free
(
oldDN
);
break
;
}
/* make sure new and original are not same to avoid deadlocks */
if
(
strcmp
(
newDN
,
origDN
->
e_ndn
)
==
0
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"<= %s alias is same as original %s
\n
"
,
oldDN
,
origDN
->
e_ndn
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_ALIAS_DEREF_PROBLEM
,
NULL
,
"circular alias"
,
NULL
);
free
(
newDN
);
free
(
oldDN
);
break
;
}
/*
* ok, so what happens if there is an alias in the DN of a dereferenced
* alias object?
*/
if
(
(
e
=
bdb2i_dn2entry_r
(
be
,
newDN
,
&
matched
))
==
NULL
)
{
/* could not deref return error */
Debug
(
LDAP_DEBUG_TRACE
,
"<= %s is a dangling alias to %s
\n
"
,
oldDN
,
newDN
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_ALIAS_DEREF_PROBLEM
,
NULL
,
"dangling alias"
,
NULL
);
if
(
matched
!=
NULL
)
free
(
matched
);
free
(
newDN
);
free
(
oldDN
);
break
;
}
free
(
newDN
);
free
(
oldDN
);
}
else
{
/*
* there was an aliasedobjectname defined but no data.
* this can't happen, right?
*/
Debug
(
LDAP_DEBUG_TRACE
,
"<= %s has no data in aliasedobjectname attribute
\n
"
,
(
e
&&
e
->
e_dn
)
?
e
->
e_dn
:
"(null)"
,
0
,
0
);
send_ldap_result
(
conn
,
op
,
LDAP_ALIAS_PROBLEM
,
NULL
,
"alias missing aliasedObjectname"
,
NULL
);
break
;
}
}
/*
* warn if we pulled out due to exceeding the maximum deref depth
*/
if
(
depth
>=
be
->
be_maxDerefDepth
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"<= deref(
\"
%s
\"
) exceeded maximum deref depth (%d) at
\"
%s
\"\n
"
,
origDN
->
e_dn
?
origDN
->
e_dn
:
"(null)"
,
be
->
be_maxDerefDepth
,
(
e
&&
e
->
e_ndn
)
?
e
->
e_ndn
:
"(null)"
);
send_ldap_result
(
conn
,
op
,
LDAP_ALIAS_DEREF_PROBLEM
,
NULL
,
"maximum alias dereference depth exceeded"
,
NULL
);
}
return
e
;
}
/*
* given a DN fully deref it and return the real DN or original DN if it fails
* This involves finding the last matched part then reconstructing forward
* e.g.
* ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
* loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
* dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
* dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
* remainder is ou=MyOU
* dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
* release lock on o=MyAliasedOrg,c=MyCountry entry
* reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
* release lock on o=MyOrg,c=MyCountry entry
*/
char
*
bdb2i_derefDN
(
BackendDB
*
be
,
Connection
*
conn
,
Operation
*
op
,
char
*
dn
)
{
struct
ldbminfo
*
li
=
(
struct
ldbminfo
*
)
be
->
be_private
;
char
*
matched
=
0
;
char
*
newDN
=
NULL
;
int
depth
,
i
;
Entry
*
eMatched
;
Entry
*
eDeref
;
Entry
*
eNew
;
if
(
!
dn
)
return
NULL
;
Debug
(
LDAP_DEBUG_TRACE
,
"<= dereferencing dn:
\"
%s
\"\n
"
,
dn
,
0
,
0
);
newDN
=
ch_strdup
(
dn
);
/* while we don't have a matched dn, deref the DN */
for
(
depth
=
0
;
(
(
eMatched
=
bdb2i_dn2entry_r
(
be
,
newDN
,
&
matched
))
==
NULL
)
&&
(
depth
<
be
->
be_maxDerefDepth
);
++
depth
)
{
if
((
matched
!=
NULL
)
&&
*
matched
)
{
char
*
submatch
;
/*
* make sure there actually is an entry for the matched part
*/
if
(
(
eMatched
=
bdb2i_dn2entry_r
(
be
,
matched
,
&
submatch
))
!=
NULL
)
{
char
*
remainder
;
/* part before the aliased part */
int
rlen
=
strlen
(
newDN
)
-
strlen
(
matched
);
Debug
(
LDAP_DEBUG_TRACE
,
"<= matched %s
\n
"
,
matched
,
0
,
0
);
remainder
=
ch_malloc
(
rlen
+
1
);
strncpy
(
remainder
,
newDN
,
rlen
);
remainder
[
rlen
]
=
'\0'
;
Debug
(
LDAP_DEBUG_TRACE
,
"<= remainder %s
\n
"
,
remainder
,
0
,
0
);
if
((
eNew
=
bdb2i_derefAlias_r
(
be
,
conn
,
op
,
eMatched
))
==
NULL
)
{
free
(
matched
);
matched
=
NULL
;
free
(
newDN
);
newDN
=
NULL
;
free
(
remainder
);
remainder
=
NULL
;
bdb2i_cache_return_entry_r
(
&
li
->
li_cache
,
eMatched
);
eMatched
=
NULL
;
break
;
/* no associated entry, dont deref */
}
else
{
Debug
(
LDAP_DEBUG_TRACE
,
"<= l&g we have %s vs %s
\n
"
,
matched
,
eNew
->
e_dn
,
0
);
i
=
strcasecmp
(
matched
,
eNew
->
e_dn
);
/* free reader lock */
bdb2i_cache_return_entry_r
(
&
li
->
li_cache
,
eNew
);
free
(
matched
);
matched
=
NULL
;
if
(
!
i
)
{
/* newDN same as old so not an alias, no need to go further */
free
(
newDN
);
newDN
=
NULL
;
free
(
remainder
);
bdb2i_cache_return_entry_r
(
&
li
->
li_cache
,
eMatched
);
eMatched
=
NULL
;
break
;
}
/*
* we have dereferenced the aliased part so put
* the new dn together
*/
free
(
newDN
);
newDN
=
ch_malloc
(
strlen
(
eMatched
->
e_dn
)
+
rlen
+
1
);
strcpy
(
newDN
,
remainder
);
strcat
(
newDN
,
eMatched
->
e_dn
);
Debug
(
LDAP_DEBUG_TRACE
,
"<= expanded to %s
\n
"
,
newDN
,
0
,
0
);
free
(
remainder
);
}
/* free reader lock */
bdb2i_cache_return_entry_r
(
&
li
->
li_cache
,
eMatched
);
}
else
{
if
(
submatch
!=
NULL
)
free
(
submatch
);
break
;
/* there was no entry for the matched part */
}
}
else
{
break
;
/* there was no matched part */
}
}
/* release lock if a match terminated the loop, there should be no
* outstanding locks at this point
*/
if
(
eMatched
!=
NULL
)
{
/* free reader lock */
bdb2i_cache_return_entry_r
(
&
li
->
li_cache
,
eMatched
);
}
/*
* the final part of the DN might be an alias so try to dereference it.
* e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
* and the above loop complete but we would still be left with an aliased DN.
*/
if
(
newDN
!=
NULL
)
{
if
(
(
eNew
=
bdb2i_dn2entry_r
(
be
,
newDN
,
&
matched
))
!=
NULL
)
{
if
((
eDeref
=
bdb2i_derefAlias_r
(
be
,
conn
,
op
,
eNew
))
!=
NULL
)
{
free
(
newDN
);
newDN
=
ch_strdup
(
eDeref
->
e_dn
);
/* free reader lock */
bdb2i_cache_return_entry_r
(
&
li
->
li_cache
,
eDeref
);
}
/* free reader lock */
bdb2i_cache_return_entry_r
(
&
li
->
li_cache
,
eNew
);
}
}
if
(
matched
!=
NULL
)
free
(
matched
);
/*
* warn if we exceeded the max depth as the resulting DN may not be dereferenced
*/
if
(
depth
>=
be
->
be_maxDerefDepth
)
{
if
(
newDN
)
{
Debug
(
LDAP_DEBUG_TRACE
,
"<= max deref depth exceeded in derefDN for
\"
%s
\"
, result
\"
%s
\"\n
"
,
dn
,
newDN
,
0
);
free
(
newDN
);
newDN
=
NULL
;
}
else
{
Debug
(
LDAP_DEBUG_TRACE
,
"<= max deref depth exceeded in derefDN for
\"
%s
\"
, result NULL
\n
"
,
dn
,
0
,
0
);
}
send_ldap_result
(
conn
,
op
,
LDAP_ALIAS_DEREF_PROBLEM
,
NULL
,
"maximum alias dereference depth exceeded for base"
,
NULL
);
}
if
(
newDN
==
NULL
)
{
newDN
=
ch_strdup
(
dn
);
}
Debug
(
LDAP_DEBUG_TRACE
,
"<= returning deref DN of
\"
%s
\"\n
"
,
newDN
,
0
,
0
);