diff options
Diffstat (limited to 'ldap/servers/slapd/extendop.c')
-rw-r--r-- | ldap/servers/slapd/extendop.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/ldap/servers/slapd/extendop.c b/ldap/servers/slapd/extendop.c new file mode 100644 index 00000000..8044f2f3 --- /dev/null +++ b/ldap/servers/slapd/extendop.c @@ -0,0 +1,297 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* extendedop.c - handle an LDAPv3 extended operation */ + +#include <stdio.h> +#include "slap.h" + +static const char *extended_op_oid2string( const char *oid ); + + +/********** this stuff should probably be moved when it's done **********/ + +static void extop_handle_import_start(Slapi_PBlock *pb, char *extoid, + struct berval *extval) +{ + char *suffix; + Slapi_DN *sdn = NULL; + Slapi_Backend *be = NULL; + struct berval bv; + int ret; + + if (extval == NULL || extval->bv_val == NULL) { + LDAPDebug(LDAP_DEBUG_ANY, + "extop_handle_import_start: no data supplied\n", 0, 0, 0); + send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, + "no data supplied", 0, NULL); + return; + } + suffix = slapi_ch_malloc(extval->bv_len+1); + strncpy(suffix, extval->bv_val, extval->bv_len); + suffix[extval->bv_len] = 0; + + sdn = slapi_sdn_new_dn_byval(suffix); + if (!sdn) { + LDAPDebug(LDAP_DEBUG_ANY, + "extop_handle_import_start: out of memory\n", 0, 0, 0); + send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL); + return; + } + /* be = slapi_be_select(sdn); */ + be = slapi_mapping_tree_find_backend_for_sdn(sdn); + slapi_sdn_free(&sdn); + if (be == NULL || be == defbackend_get_backend()) { + /* might be instance name instead of suffix */ + be = slapi_be_select_by_instance_name(suffix); + } + if (be == NULL || be == defbackend_get_backend()) { + LDAPDebug(LDAP_DEBUG_ANY, + "bulk import: invalid suffix or instance name '%s'\n", + suffix, 0, 0); + send_ldap_result(pb, LDAP_NO_SUCH_OBJECT, NULL, + "invalid suffix or instance name", 0, NULL); + goto out; + } + + slapi_pblock_set(pb, SLAPI_BACKEND, be); + slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot ); + + { + /* Access Control Check to see if the client is + * allowed to use task import + */ + char *dummyAttr = "dummy#attr"; + char *dummyAttrs[2] = { NULL, NULL }; + int rc = 0; + char dn[128]; + Slapi_Entry *feature; + + /* slapi_str2entry modify its dn parameter so we must copy + * this string each time we call it ! + */ + sprintf(dn, "dn: oid=%s,cn=features,cn=config", + EXTOP_BULK_IMPORT_START_OID); + + dummyAttrs[0] = dummyAttr; + feature = slapi_str2entry(dn, 0); + rc = plugin_call_acl_plugin (pb, feature, dummyAttrs, NULL, + SLAPI_ACL_WRITE, ACLPLUGIN_ACCESS_DEFAULT, NULL); + slapi_entry_free(feature); + if (rc != LDAP_SUCCESS) + { + /* Client isn't allowed to do this. */ + send_ldap_result(pb, rc, NULL, NULL, 0, NULL); + goto out; + } + } + + if (be->be_wire_import == NULL) { + /* not supported by this backend */ + LDAPDebug(LDAP_DEBUG_ANY, + "bulk import attempted on '%s' (not supported)\n", + suffix, 0, 0); + send_ldap_result(pb, LDAP_NOT_SUPPORTED, NULL, NULL, 0, NULL); + goto out; + } + + ret = SLAPI_UNIQUEID_GENERATE_TIME_BASED; + slapi_pblock_set(pb, SLAPI_LDIF2DB_GENERATE_UNIQUEID, &ret); + ret = SLAPI_BI_STATE_START; + slapi_pblock_set(pb, SLAPI_BULK_IMPORT_STATE, &ret); + ret = (*be->be_wire_import)(pb); + if (ret != 0) { + LDAPDebug(LDAP_DEBUG_ANY, + "extop_handle_import_start: error starting import (%d)\n", + ret, 0, 0); + send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL); + goto out; + } + + /* okay, the import is starting now -- save the backend in the + * connection block & mark this connection as belonging to a bulk import + */ + PR_Lock(pb->pb_conn->c_mutex); + pb->pb_conn->c_flags |= CONN_FLAG_IMPORT; + pb->pb_conn->c_bi_backend = be; + PR_Unlock(pb->pb_conn->c_mutex); + + slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, EXTOP_BULK_IMPORT_START_OID); + bv.bv_val = NULL; + bv.bv_len = 0; + slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, &bv); + send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); + LDAPDebug(LDAP_DEBUG_ANY, + "Bulk import: begin import on '%s'.\n", suffix, 0, 0); + +out: + slapi_ch_free((void **)&suffix); + return; +} + +static void extop_handle_import_done(Slapi_PBlock *pb, char *extoid, + struct berval *extval) +{ + Slapi_Backend *be; + struct berval bv; + int ret; + + PR_Lock(pb->pb_conn->c_mutex); + pb->pb_conn->c_flags &= ~CONN_FLAG_IMPORT; + be = pb->pb_conn->c_bi_backend; + pb->pb_conn->c_bi_backend = NULL; + PR_Unlock(pb->pb_conn->c_mutex); + + if ((be == NULL) || (be->be_wire_import == NULL)) { + /* can this even happen? */ + LDAPDebug(LDAP_DEBUG_ANY, + "extop_handle_import_done: backend not supported\n", + 0, 0, 0); + send_ldap_result(pb, LDAP_NOT_SUPPORTED, NULL, NULL, 0, NULL); + return; + } + + /* signal "done" to the backend */ + slapi_pblock_set(pb, SLAPI_BACKEND, be); + slapi_pblock_set(pb, SLAPI_BULK_IMPORT_ENTRY, NULL); + ret = SLAPI_BI_STATE_DONE; + slapi_pblock_set(pb, SLAPI_BULK_IMPORT_STATE, &ret); + ret = (*be->be_wire_import)(pb); + if (ret != 0) { + LDAPDebug(LDAP_DEBUG_ANY, + "bulk import: error ending import (%d)\n", + ret, 0, 0); + send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL); + return; + } + + /* more goofiness */ + slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, EXTOP_BULK_IMPORT_DONE_OID); + bv.bv_val = NULL; + bv.bv_len = 0; + slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, &bv); + send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); + LDAPDebug(LDAP_DEBUG_ANY, + "Bulk import completed successfully.\n", 0, 0, 0); + return; +} + + +void +do_extended( Slapi_PBlock *pb ) +{ + char *extoid = NULL, *errmsg; + struct berval extval = {0}; + int lderr, rc; + unsigned long len, tag; + const char *name; + + LDAPDebug( LDAP_DEBUG_TRACE, "do_extended\n", 0, 0, 0 ); + + /* + * Parse the extended request. It looks like this: + * + * ExtendedRequest := [APPLICATION 23] SEQUENCE { + * requestName [0] LDAPOID, + * requestValue [1] OCTET STRING OPTIONAL + * } + */ + + if ( ber_scanf( pb->pb_op->o_ber, "{a", &extoid ) + == LBER_ERROR ) { + LDAPDebug( LDAP_DEBUG_ANY, + "ber_scanf failed (op=extended; params=OID)\n", + 0, 0, 0 ); + op_shared_log_error_access (pb, "EXT", "???", "decoding error: fail to get extension OID"); + send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, + NULL ); + goto free_and_return; + } + tag = ber_peek_tag(pb->pb_op->o_ber, &len); + + if (tag == LDAP_TAG_EXOP_REQ_VALUE) { + if ( ber_scanf( pb->pb_op->o_ber, "o}", &extval ) == LBER_ERROR ) { + op_shared_log_error_access (pb, "EXT", "???", "decoding error: fail to get extension value"); + send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, + NULL ); + goto free_and_return; + } + } else { + if ( ber_scanf( pb->pb_op->o_ber, "}") == LBER_ERROR ) { + op_shared_log_error_access (pb, "EXT", "???", "decoding error"); + send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, + NULL ); + goto free_and_return; + } + } + if ( NULL == ( name = extended_op_oid2string( extoid ))) { + LDAPDebug( LDAP_DEBUG_ARGS, "do_extended: oid (%s)\n", extoid, 0, 0 ); + + slapi_log_access( LDAP_DEBUG_STATS, "conn=%d op=%d EXT oid=\"%s\"\n", + pb->pb_conn->c_connid, pb->pb_op->o_opid, extoid ); + } else { + LDAPDebug( LDAP_DEBUG_ARGS, "do_extended: oid (%s-%s)\n", + extoid, name, 0 ); + + slapi_log_access( LDAP_DEBUG_STATS, + "conn=%d op=%d EXT oid=\"%s\" name=\"%s\"\n", + pb->pb_conn->c_connid, pb->pb_op->o_opid, extoid, name ); + } + + /* during a bulk import, only BULK_IMPORT_DONE is allowed! + * (and this is the only time it's allowed) + */ + if (pb->pb_conn->c_flags & CONN_FLAG_IMPORT) { + if (strcmp(extoid, EXTOP_BULK_IMPORT_DONE_OID) != 0) { + send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL); + goto free_and_return; + } + extop_handle_import_done(pb, extoid, &extval); + goto free_and_return; + } + + if (strcmp(extoid, EXTOP_BULK_IMPORT_START_OID) == 0) { + extop_handle_import_start(pb, extoid, &extval); + goto free_and_return; + } + + slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_OID, extoid ); + slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_VALUE, &extval ); + rc = plugin_call_exop_plugins( pb, extoid ); + + if ( SLAPI_PLUGIN_EXTENDED_SENT_RESULT != rc ) { + if ( SLAPI_PLUGIN_EXTENDED_NOT_HANDLED == rc ) { + lderr = LDAP_PROTOCOL_ERROR; /* no plugin handled the op */ + errmsg = "unsupported extended operation"; + } else { + errmsg = NULL; + lderr = rc; + } + send_ldap_result( pb, lderr, NULL, errmsg, 0, NULL ); + } +free_and_return: + if (extoid) + slapi_ch_free((void **)&extoid); + if (extval.bv_val) + slapi_ch_free((void **)&extval.bv_val); + return; +} + + +static const char * +extended_op_oid2string( const char *oid ) +{ + const char *rval = NULL; + + if ( 0 == strcmp(oid, EXTOP_BULK_IMPORT_START_OID)) { + rval = "Netscape Bulk Import Start"; + } else if ( 0 == strcmp(oid, EXTOP_BULK_IMPORT_DONE_OID)) { + rval = "Netscape Bulk Import End"; + } else { + rval = plugin_extended_op_oid2string( oid ); + } + + return( rval ); +} |