Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
53 deleted
122 edited
57 copied

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source4/lib/cmdline/popt_common.c

    r414 r745  
    6767
    6868        if (reason == POPT_CALLBACK_REASON_POST) {
    69                 if (lp_configfile(cmdline_lp_ctx) == NULL) {
    70             lp_load_default(cmdline_lp_ctx);
     69                if (lpcfg_configfile(cmdline_lp_ctx) == NULL) {
     70                        lpcfg_load_default(cmdline_lp_ctx);
    7171                }
    7272                /* Hook any 'every Samba program must do this, after
     
    8484
    8585        if (reason == POPT_CALLBACK_REASON_PRE) {
    86                 cmdline_lp_ctx = loadparm_init(talloc_autofree_context());
     86                cmdline_lp_ctx = loadparm_init_global(false);
    8787
    8888                /* Hook for 'almost the first thing to do in a samba program' here */
     
    109109
    110110        case OPT_OPTION:
    111                 if (!lp_set_option(cmdline_lp_ctx, arg)) {
     111                if (!lpcfg_set_option(cmdline_lp_ctx, arg)) {
    112112                        fprintf(stderr, "Error setting option '%s'\n", arg);
    113113                        exit(1);
     
    116116
    117117        case 'd':
    118                 lp_set_cmdline(cmdline_lp_ctx, "log level", arg);
     118                lpcfg_set_cmdline(cmdline_lp_ctx, "log level", arg);
    119119                break;
    120120
     
    125125        case 's':
    126126                if (arg) {
    127                         lp_load(cmdline_lp_ctx, arg);
     127                        lpcfg_load(cmdline_lp_ctx, arg);
    128128                }
    129129                break;
     
    132132                if (arg) {
    133133                        char *new_logfile = talloc_asprintf(NULL, "%s/log.%s", arg, pname);
    134                         lp_set_cmdline(cmdline_lp_ctx, "log file", new_logfile);
     134                        lpcfg_set_cmdline(cmdline_lp_ctx, "log file", new_logfile);
    135135                        talloc_free(new_logfile);
    136136                }
     
    153153        case 'O':
    154154                if (arg) {
    155                         lp_set_cmdline(lp_ctx, "socket options", arg);
     155                        lpcfg_set_cmdline(lp_ctx, "socket options", arg);
    156156                }
    157157                break;
    158158       
    159159        case 'W':
    160                 lp_set_cmdline(lp_ctx, "workgroup", arg);
     160                lpcfg_set_cmdline(lp_ctx, "workgroup", arg);
    161161                break;
    162162
    163163        case 'r':
    164                 lp_set_cmdline(lp_ctx, "realm", arg);
     164                lpcfg_set_cmdline(lp_ctx, "realm", arg);
    165165                break;
    166166               
    167167        case 'n':
    168                 lp_set_cmdline(lp_ctx, "netbios name", arg);
     168                lpcfg_set_cmdline(lp_ctx, "netbios name", arg);
    169169                break;
    170170               
    171171        case 'i':
    172                 lp_set_cmdline(lp_ctx, "netbios scope", arg);
     172                lpcfg_set_cmdline(lp_ctx, "netbios scope", arg);
    173173                break;
    174174
    175175        case 'm':
    176                 lp_set_cmdline(lp_ctx, "client max protocol", arg);
     176                lpcfg_set_cmdline(lp_ctx, "client max protocol", arg);
    177177                break;
    178178
    179179        case 'R':
    180                 lp_set_cmdline(lp_ctx, "name resolve order", arg);
     180                lpcfg_set_cmdline(lp_ctx, "name resolve order", arg);
    181181                break;
    182182
    183183        case 'S':
    184                 lp_set_cmdline(lp_ctx, "client signing", arg);
     184                lpcfg_set_cmdline(lp_ctx, "client signing", arg);
    185185                break;
    186186
  • trunk/server/source4/lib/cmdline/popt_credentials.c

    r414 r745  
    3232 *              -N,--no-pass
    3333 *              -S,--signing
    34  *              -P --machine-pass
    35  *                 --simple-bind-dn
    36  *                 --password
     34 *              -P,--machine-pass
     35 *              --simple-bind-dn
     36 *              --password
    3737 */
    3838
     39static bool dont_ask;
     40static bool machine_account_pending;
    3941
    40 static bool dont_ask;
    41 
    42 enum opt { OPT_SIMPLE_BIND_DN, OPT_PASSWORD, OPT_KERBEROS };
     42enum opt { OPT_SIMPLE_BIND_DN, OPT_PASSWORD, OPT_KERBEROS, OPT_SIGN, OPT_ENCRYPT };
    4343
    4444/*
     
    6666                        cli_credentials_set_cmdline_callbacks(cmdline_credentials);
    6767                }
     68
     69                if (machine_account_pending) {
     70                        cli_credentials_set_machine_account(cmdline_credentials, cmdline_lp_ctx);
     71                }
     72
    6873                return;
     74
    6975        }
    7076
     
    97103        case 'P':
    98104                /* Later, after this is all over, get the machine account details from the secrets.ldb */
    99                 cli_credentials_set_machine_account_pending(cmdline_credentials, cmdline_lp_ctx);
     105                machine_account_pending = true;
    100106                break;
    101107
     
    106112                if (arg) {
    107113                        if (!set_boolean(arg, &use_kerberos)) {
    108                                 fprintf(stderr, "Error parsing -k %s\n", arg);
     114                                fprintf(stderr, "Error parsing -k %s. Should be "
     115                                        "-k [yes|no]\n", arg);
    109116                                exit(1);
    110117                                break;
     
    120127               
    121128        case OPT_SIMPLE_BIND_DN:
     129        {
    122130                cli_credentials_set_bind_dn(cmdline_credentials, arg);
    123131                break;
     132        }
     133        case OPT_SIGN:
     134        {
     135                uint32_t gensec_features;
     136
     137                gensec_features = cli_credentials_get_gensec_features(cmdline_credentials);
     138
     139                gensec_features |= GENSEC_FEATURE_SIGN;
     140                cli_credentials_set_gensec_features(cmdline_credentials,
     141                                                    gensec_features);
     142                break;
     143        }
     144        case OPT_ENCRYPT:
     145        {
     146                uint32_t gensec_features;
     147
     148                gensec_features = cli_credentials_get_gensec_features(cmdline_credentials);
     149
     150                gensec_features |= GENSEC_FEATURE_SEAL;
     151                cli_credentials_set_gensec_features(cmdline_credentials,
     152                                                    gensec_features);
     153                break;
     154        }
    124155        }
    125156}
     
    135166        { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password (implies -k)" },
    136167        { "simple-bind-dn", 0, POPT_ARG_STRING, NULL, OPT_SIMPLE_BIND_DN, "DN to use for a simple bind" },
    137         { "kerberos", 'k', POPT_ARG_STRING, NULL, OPT_KERBEROS, "Use Kerberos" },
     168        { "kerberos", 'k', POPT_ARG_STRING, NULL, OPT_KERBEROS, "Use Kerberos, -k [yes|no]" },
     169        { "sign", 'S', POPT_ARG_NONE, NULL, OPT_SIGN, "Sign connection to prevent modification in transit" },
     170        { "encrypt", 'e', POPT_ARG_NONE, NULL, OPT_ENCRYPT, "Encrypt connection for privacy" },
    138171        { NULL }
    139172};
  • trunk/server/source4/lib/com/dcom/main.c

    r414 r745  
    172172                return dcerpc_pipe_connect(ctx->event_ctx, p, "ncalrpc",
    173173                                                                   &ndr_table_IRemoteActivation,
    174                                                                    dcom_get_server_credentials(ctx, NULL), ctx->event_ctx, ctx->lp_ctx);
     174                                                                   dcom_get_server_credentials(ctx, NULL), ctx->event_ctx, ctx->lp_ctx);
    175175        }
    176176        loc_ctx = talloc_new(ctx);
     
    183183                status = dcerpc_pipe_connect_b(ctx->event_ctx, p, bd,
    184184                                                                           &ndr_table_IRemoteActivation,
    185                                                                    dcom_get_server_credentials(ctx, bd->host), ctx->event_ctx, ctx->lp_ctx);
     185                                                                   dcom_get_server_credentials(ctx, bd->host), ctx->event_ctx, ctx->lp_ctx);
    186186                goto end;
    187187        }
     
    705705                return;
    706706        }
    707 
     707/*TODO: FIXME - for now this unused anyway */
    708708        req = dcerpc_ndr_request_send(p, &s->d->obj.u_objref.u_standard.std.ipid, s->table, s->opnum, s, s->r);
    709709        composite_continue_rpc(c, req, s->continuation, c);
  • trunk/server/source4/lib/com/main.c

    r414 r745  
    5353
    5454        /* Run IClassFactory::CreateInstance() */
    55         error = IClassFactory_CreateInstance(factory, ctx, NULL, &classfact_iid, &iunk);
     55        error = IClassFactory_CreateInstance(factory, ctx, NULL, &classfact_iid, (struct MInterfacePointer *) &iunk);
    5656        if (!W_ERROR_IS_OK(error)) {
    5757                DEBUG(3, ("Error while calling IClassFactory::CreateInstance : %s\n", win_errstr(error)));
  • trunk/server/source4/lib/com/pycom.c

    r414 r745  
    1818*/
    1919
     20#include <Python.h>
    2021#include "includes.h"
    21 #include <Python.h>
    2222#include "lib/com/com.h"
    2323#include "librpc/ndr/libndr.h"
    2424#include "libcli/util/pyerrors.h"
    25 
    26 #ifndef Py_RETURN_NONE
    27 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
    28 #endif
    2925
    3026static struct com_context *py_com_ctx = NULL; /* FIXME: evil global */
  • trunk/server/source4/lib/events/events.h

    r414 r745  
    22#define __LIB_EVENTS_H__
    33#define TEVENT_COMPAT_DEFINES 1
    4 #include <../lib/tevent/tevent.h>
     4#include <tevent.h>
    55struct tevent_context *s4_event_context_init(TALLOC_CTX *mem_ctx);
    66struct tevent_context *event_context_find(TALLOC_CTX *mem_ctx) _DEPRECATED_;
     7void s4_event_context_set_default(struct tevent_context *ev);
    78#endif /* __LIB_EVENTS_H__ */
  • trunk/server/source4/lib/events/tevent_s4.c

    r414 r745  
    7272}
    7373
    74 /*
    75   find an event context that is a parent of the given memory context,
    76   or create a new event context as a child of the given context if
    77   none is found
    78 
    79   This should be used in preference to event_context_init() in places
    80   where you would prefer to use the existing event context if possible
    81   (which is most situations)
    82 */
    83 struct tevent_context *event_context_find(TALLOC_CTX *mem_ctx)
    84 {
    85         struct tevent_context *ev = talloc_find_parent_bytype(mem_ctx, struct tevent_context);
    86         if (ev == NULL) {               
    87                 ev = tevent_context_init(mem_ctx);
    88         }
    89         return ev;
    90 }
  • trunk/server/source4/lib/ldb-samba/ldif_handlers.c

    r414 r745  
    33
    44   Copyright (C) Andrew Tridgell 2005
    5    Copyright (C) Andrew Bartlett 2006-2007
     5   Copyright (C) Andrew Bartlett 2006-2009
    66   Copyright (C) Matthias Dieter Wallnöfer 2009
    77     ** NOTE! The following LGPL license applies to the ldb
     
    2424
    2525#include "includes.h"
    26 #include "lib/ldb/include/ldb.h"
    27 #include "lib/ldb/include/ldb_module.h"
     26#include <ldb.h>
     27#include <ldb_module.h>
    2828#include "ldb_handlers.h"
    2929#include "dsdb/samdb/samdb.h"
     
    3131#include "librpc/gen_ndr/ndr_misc.h"
    3232#include "librpc/gen_ndr/ndr_drsblobs.h"
     33#include "librpc/gen_ndr/ndr_dnsp.h"
    3334#include "librpc/ndr/libndr.h"
    3435#include "libcli/security/security.h"
    3536#include "param/param.h"
     37#include "../lib/util/asn1.h"
    3638
    3739/*
    3840  use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
     41
     42  If mask_errors is true, then function succeeds but out data
     43  is set to "<Unable to decode binary data>" message
     44
     45  \return 0 on success; -1 on error
    3946*/
    4047static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
     
    4249                          size_t struct_size,
    4350                          ndr_pull_flags_fn_t pull_fn,
    44                           ndr_print_fn_t print_fn)
     51                          ndr_print_fn_t print_fn,
     52                          bool mask_errors)
    4553{
    4654        uint8_t *p;
     
    5159        p = talloc_size(mem_ctx, struct_size);
    5260        err = ndr_pull_struct_blob(in, mem_ctx,
    53                                    lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
    5461                                   p, pull_fn);
    5562        if (err != NDR_ERR_SUCCESS) {
     63                /* fail in not in mask_error mode */
     64                if (!mask_errors) {
     65                        return -1;
     66                }
    5667                talloc_free(p);
    5768                out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
     
    8091                return -1;
    8192        }
    82         ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, sid,
     93        ndr_err = ndr_push_struct_blob(out, mem_ctx, sid,
    8394                                       (ndr_push_flags_fn_t)ndr_push_dom_sid);
    8495        talloc_free(sid);
     
    92103  convert a NDR formatted blob to a ldif formatted objectSid
    93104*/
    94 static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
     105int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
    95106                                const struct ldb_val *in, struct ldb_val *out)
    96107{
     
    102113                return -1;
    103114        }
    104         ndr_err = ndr_pull_struct_blob_all(in, sid, NULL, sid,
     115        ndr_err = ndr_pull_struct_blob_all(in, sid, sid,
    105116                                           (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
    106117        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    116127}
    117128
    118 static bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
     129bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
    119130{
    120131        if (v->length < 3) {
     
    199210
    200211        /* Check it looks like a SID */
    201         ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, NULL, &sid,
     212        ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, &sid,
    202213                                           (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
    203214        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    215226        struct GUID guid;
    216227        NTSTATUS status;
    217         enum ndr_err_code ndr_err;
    218228
    219229        status = GUID_from_data_blob(in, &guid);
     
    222232        }
    223233
    224         ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, &guid,
    225                                        (ndr_push_flags_fn_t)ndr_push_GUID);
    226         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     234        status = GUID_to_ndr_blob(&guid, mem_ctx, out);
     235        if (!NT_STATUS_IS_OK(status)) {
    227236                return -1;
    228237        }
     
    237246{
    238247        struct GUID guid;
    239         enum ndr_err_code ndr_err;
    240         ndr_err = ndr_pull_struct_blob_all(in, mem_ctx, NULL, &guid,
    241                                            (ndr_pull_flags_fn_t)ndr_pull_GUID);
    242         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     248        NTSTATUS status;
     249
     250        status = GUID_from_ndr_blob(in, &guid);
     251        if (!NT_STATUS_IS_OK(status)) {
    243252                return -1;
    244253        }
     
    263272{
    264273        struct GUID guid;
    265         enum ndr_err_code ndr_err;
     274        NTSTATUS status;
     275
    266276        if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
    267277                return 0;
     
    283293       
    284294        /* Check it looks like a GUID */
    285         ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, NULL, &guid,
    286                                            (ndr_pull_flags_fn_t)ndr_pull_GUID);
    287         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     295        status = GUID_from_ndr_blob(out, &guid);
     296        if (!NT_STATUS_IS_OK(status)) {
     297                data_blob_free(out);
    288298                return -1;
    289299        }
     
    356366        }
    357367
    358         ndr_err = ndr_pull_struct_blob(in, sd, NULL, sd,
     368        ndr_err = ndr_pull_struct_blob(in, sd, sd,
    359369                                       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
    360370        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    361371                /* If this does not parse, then it is probably SDDL, and we should try it that way */
    362                
     372
    363373                const struct dom_sid *sid = samdb_domain_sid(ldb);
    364374                talloc_free(sd);
     
    369379        }
    370380
    371         ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, sd,
     381        ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
    372382                                       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
    373383        talloc_free(sd);
     
    392402                                      sizeof(struct security_descriptor),
    393403                                      (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
    394                                       (ndr_print_fn_t)ndr_print_security_descriptor);
     404                                      (ndr_print_fn_t)ndr_print_security_descriptor,
     405                                      true);
    395406                                     
    396407        }
     
    401412        }
    402413        /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
    403         ndr_err = ndr_pull_struct_blob(in, sd, NULL, sd,
     414        ndr_err = ndr_pull_struct_blob(in, sd, sd,
    404415                                           (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
    405416        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    407418                return -1;
    408419        }
    409         out->data = (uint8_t *)sddl_encode(mem_ctx, sd, NULL);
     420        out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
    410421        talloc_free(sd);
    411422        if (out->data == NULL) {
     
    417428
    418429/*
    419    canonicalise an objectCategory.  We use the short form as the cannoical form:
     430   canonicalise an objectCategory.  We use the short form as the canonical form:
    420431   cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
    421432*/
     
    425436{
    426437        struct ldb_dn *dn1 = NULL;
    427         const struct dsdb_schema *schema = dsdb_get_schema(ldb);
     438        const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
    428439        const struct dsdb_class *sclass;
    429440        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     
    477488                                          const struct ldb_val *v2)
    478489{
    479 
    480         int ret, ret1, ret2;
    481         struct ldb_val v1_canon, v2_canon;
    482         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    483 
    484         /* I could try and bail if tmp_ctx was NULL, but what return
    485          * value would I use?
    486          *
    487          * It seems easier to continue on the NULL context
    488          */
    489         ret1 = ldif_canonicalise_objectCategory(ldb, tmp_ctx, v1, &v1_canon);
    490         ret2 = ldif_canonicalise_objectCategory(ldb, tmp_ctx, v2, &v2_canon);
    491 
    492         if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
    493                 ret = data_blob_cmp(&v1_canon, &v2_canon);
    494         } else {
    495                 ret = data_blob_cmp(v1, v2);
    496         }
    497         talloc_free(tmp_ctx);
    498         return ret;
     490        return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
     491                                  v1, v2);
     492}
     493
     494/*
     495  convert a NDR formatted blob to a ldif formatted schemaInfo
     496*/
     497static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
     498                                 const struct ldb_val *in, struct ldb_val *out)
     499{
     500        return ldif_write_NDR(ldb, mem_ctx, in, out,
     501                              sizeof(struct repsFromToBlob),
     502                              (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
     503                              (ndr_print_fn_t)ndr_print_schemaInfoBlob,
     504                              true);
    499505}
    500506
     
    508514        enum ndr_err_code ndr_err;
    509515        char *string, *line, *p, *oid;
     516        DATA_BLOB oid_blob;
    510517
    511518        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     
    517524        blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
    518525        if (blob == NULL) {
    519                 talloc_free(blob);
    520                 return -1;
    521         }
    522 
     526                talloc_free(tmp_ctx);
     527                return -1;
     528        }
     529
     530        /* use the switch value to detect if this is in the binary
     531         * format
     532         */
     533        if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
     534                ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
     535                                               (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
     536                if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     537                        ndr_err = ndr_push_struct_blob(out, mem_ctx,
     538                                                       blob,
     539                                                       (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
     540                        talloc_free(tmp_ctx);
     541                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     542                                return -1;
     543                        }
     544                        return 0;
     545                }
     546        }
     547
     548        /* If this does not parse, then it is probably the text version, and we should try it that way */
    523549        blob->version = PREFIX_MAP_VERSION_DSDB;
    524550       
     
    540566                        }
    541567                }
    542                 /* allow a traling seperator */
     568                /* allow a trailing separator */
    543569                if (line == p) {
    544570                        break;
     
    564590                oid++;
    565591
    566                 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.oid
    567                         = talloc_strdup(blob->ctr.dsdb.mappings, oid);
     592                if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
     593                        talloc_free(tmp_ctx);
     594                        return -1;
     595                }
     596                blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
     597                blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
    568598
    569599                blob->ctr.dsdb.num_mappings++;
     
    578608
    579609        ndr_err = ndr_push_struct_blob(out, mem_ctx,
    580                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
    581610                                       blob,
    582611                                       (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
     
    600629
    601630        if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
    602                 return ldif_write_NDR(ldb, mem_ctx, in, out,
    603                                       sizeof(struct prefixMapBlob),
    604                                       (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
    605                                       (ndr_print_fn_t)ndr_print_prefixMapBlob);
    606                                      
     631                int err;
     632                /* try to decode the blob as S4 prefixMap */
     633                err = ldif_write_NDR(ldb, mem_ctx, in, out,
     634                                     sizeof(struct prefixMapBlob),
     635                                     (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
     636                                     (ndr_print_fn_t)ndr_print_prefixMapBlob,
     637                                     false);
     638                if (0 == err) {
     639                        return err;
     640                }
     641                /* try parsing it as Windows PrefixMap value */
     642                return ldif_write_NDR(ldb, mem_ctx, in, out,
     643                                      sizeof(struct drsuapi_MSPrefixMap_Ctr),
     644                                      (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
     645                                      (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
     646                                      true);
    607647        }
    608648
     
    612652        }
    613653        ndr_err = ndr_pull_struct_blob_all(in, blob,
    614                                            lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
    615654                                           blob,
    616655                                           (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
    617656        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    618                 talloc_free(blob);
    619                 return -1;
     657                goto failed;
    620658        }
    621659        if (blob->version != PREFIX_MAP_VERSION_DSDB) {
    622                 return -1;
     660                goto failed;
    623661        }
    624662        string = talloc_strdup(mem_ctx, "");
    625663        if (string == NULL) {
    626                 return -1;
     664                goto failed;
    627665        }
    628666
    629667        for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
     668                DATA_BLOB oid_blob;
     669                char *partial_oid = NULL;
     670
    630671                if (i > 0) {
    631672                        string = talloc_asprintf_append(string, ";");
    632673                }
     674
     675                oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
     676                                           blob->ctr.dsdb.mappings[i].oid.length);
     677                if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
     678                        DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
     679                                  blob->ctr.dsdb.mappings[i].id_prefix));
     680                        goto failed;
     681                }
    633682                string = talloc_asprintf_append(string, "%u:%s",
    634683                                                   blob->ctr.dsdb.mappings[i].id_prefix,
    635                                                    blob->ctr.dsdb.mappings[i].oid.oid);
     684                                                   partial_oid);
     685                talloc_free(discard_const(partial_oid));
    636686                if (string == NULL) {
    637                         return -1;
     687                        goto failed;
    638688                }
    639689        }
     
    642692        *out = data_blob_string_const(string);
    643693        return 0;
     694
     695failed:
     696        talloc_free(blob);
     697        return -1;
    644698}
    645699
     
    673727                                     const struct ldb_val *v2)
    674728{
    675 
    676         int ret, ret1, ret2;
    677         struct ldb_val v1_canon, v2_canon;
    678         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    679 
    680         /* I could try and bail if tmp_ctx was NULL, but what return
    681          * value would I use?
    682          *
    683          * It seems easier to continue on the NULL context
    684          */
    685         ret1 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v1, &v1_canon);
    686         ret2 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v2, &v2_canon);
    687 
    688         if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
    689                 ret = data_blob_cmp(&v1_canon, &v2_canon);
    690         } else {
    691                 ret = data_blob_cmp(v1, v2);
    692         }
    693         talloc_free(tmp_ctx);
    694         return ret;
     729        return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
     730                                  v1, v2);
     731}
     732
     733/* length limited conversion of a ldb_val to a int32_t */
     734static int val_to_int32(const struct ldb_val *in, int32_t *v)
     735{
     736        char *end;
     737        char buf[64];
     738
     739        /* make sure we don't read past the end of the data */
     740        if (in->length > sizeof(buf)-1) {
     741                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     742        }
     743        strncpy(buf, (char *)in->data, in->length);
     744        buf[in->length] = 0;
     745
     746        /* We've to use "strtoll" here to have the intended overflows.
     747         * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
     748        *v = (int32_t) strtoll(buf, &end, 0);
     749        if (*end != 0) {
     750                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     751        }
     752        return LDB_SUCCESS;
     753}
     754
     755/* length limited conversion of a ldb_val to a int64_t */
     756static int val_to_int64(const struct ldb_val *in, int64_t *v)
     757{
     758        char *end;
     759        char buf[64];
     760
     761        /* make sure we don't read past the end of the data */
     762        if (in->length > sizeof(buf)-1) {
     763                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     764        }
     765        strncpy(buf, (char *)in->data, in->length);
     766        buf[in->length] = 0;
     767
     768        *v = (int64_t) strtoll(buf, &end, 0);
     769        if (*end != 0) {
     770                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     771        }
     772        return LDB_SUCCESS;
    695773}
    696774
     
    699777                        const struct ldb_val *in, struct ldb_val *out)
    700778{
    701         char *end;
    702         /* We've to use "strtoll" here to have the intended overflows.
    703          * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
    704         int32_t i = (int32_t) strtoll((char *)in->data, &end, 0);
    705         if (*end != 0) {
    706                 return -1;
     779        int32_t i;
     780        int ret;
     781
     782        ret = val_to_int32(in, &i);
     783        if (ret != LDB_SUCCESS) {
     784                return ret;
    707785        }
    708786        out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
    709787        if (out->data == NULL) {
    710                 return -1;
     788                ldb_oom(ldb);
     789                return LDB_ERR_OPERATIONS_ERROR;
    711790        }
    712791        out->length = strlen((char *)out->data);
     
    716795/* Comparison of two 32-bit integers */
    717796static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
    718                         const struct ldb_val *v1, const struct ldb_val *v2)
    719 {
    720         /* We've to use "strtoll" here to have the intended overflows.
    721          * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
    722         return (int32_t) strtoll((char *)v1->data, NULL, 0)
    723          - (int32_t) strtoll((char *)v2->data, NULL, 0);
     797                                 const struct ldb_val *v1, const struct ldb_val *v2)
     798{
     799        int32_t i1=0, i2=0;
     800        val_to_int32(v1, &i1);
     801        val_to_int32(v2, &i2);
     802        if (i1 == i2) return 0;
     803        return i1 > i2? 1 : -1;
     804}
     805
     806/* Canonicalisation of two 64-bit integers */
     807static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
     808                                   const struct ldb_val *in, struct ldb_val *out)
     809{
     810        int64_t i;
     811        int ret;
     812
     813        ret = val_to_int64(in, &i);
     814        if (ret != LDB_SUCCESS) {
     815                return ret;
     816        }
     817        out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
     818        if (out->data == NULL) {
     819                ldb_oom(ldb);
     820                return LDB_ERR_OPERATIONS_ERROR;
     821        }
     822        out->length = strlen((char *)out->data);
     823        return 0;
     824}
     825
     826/* Comparison of two 64-bit integers */
     827static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
     828                                 const struct ldb_val *v1, const struct ldb_val *v2)
     829{
     830        int64_t i1=0, i2=0;
     831        val_to_int64(v1, &i1);
     832        val_to_int64(v2, &i2);
     833        if (i1 == i2) return 0;
     834        return i1 > i2? 1 : -1;
    724835}
    725836
     
    733844                              sizeof(struct repsFromToBlob),
    734845                              (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
    735                               (ndr_print_fn_t)ndr_print_repsFromToBlob);
     846                              (ndr_print_fn_t)ndr_print_repsFromToBlob,
     847                              true);
    736848}
    737849
     
    745857                              sizeof(struct replPropertyMetaDataBlob),
    746858                              (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
    747                               (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob);
     859                              (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
     860                              true);
    748861}
    749862
     
    757870                              sizeof(struct replUpToDateVectorBlob),
    758871                              (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
    759                               (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob);
     872                              (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
     873                              true);
     874}
     875
     876
     877/*
     878  convert a NDR formatted blob to a ldif formatted dnsRecord
     879*/
     880static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
     881                                const struct ldb_val *in, struct ldb_val *out)
     882{
     883        return ldif_write_NDR(ldb, mem_ctx, in, out,
     884                              sizeof(struct dnsp_DnssrvRpcRecord),
     885                              (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
     886                              (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
     887                              true);
     888}
     889
     890/*
     891  convert a NDR formatted blob of a supplementalCredentials into text
     892*/
     893static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
     894                                                  const struct ldb_val *in, struct ldb_val *out)
     895{
     896        return ldif_write_NDR(ldb, mem_ctx, in, out,
     897                              sizeof(struct supplementalCredentialsBlob),
     898                              (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
     899                              (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
     900                              true);
    760901}
    761902
     
    764905                                 const struct ldb_val *in, struct ldb_val *out)
    765906{
    766         *out = data_blob_string_const(data_blob_hex_string(mem_ctx, in));
     907        *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
    767908        if (!out->data) {
    768909                return -1;
     
    770911        return 0;
    771912}
     913
     914/*
     915  compare two dns
     916*/
     917static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
     918                                        const struct ldb_val *v1, const struct ldb_val *v2)
     919{
     920        struct ldb_dn *dn1 = NULL, *dn2 = NULL;
     921        int ret;
     922
     923        if (dsdb_dn_is_deleted_val(v1)) {
     924                /* If the DN is deleted, then we can't search for it */
     925                return -1;
     926        }
     927
     928        if (dsdb_dn_is_deleted_val(v2)) {
     929                /* If the DN is deleted, then we can't search for it */
     930                return -1;
     931        }
     932
     933        dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
     934        if ( ! ldb_dn_validate(dn1)) return -1;
     935
     936        dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
     937        if ( ! ldb_dn_validate(dn2)) {
     938                talloc_free(dn1);
     939                return -1;
     940        }
     941
     942        ret = ldb_dn_compare(dn1, dn2);
     943
     944        talloc_free(dn1);
     945        talloc_free(dn2);
     946        return ret;
     947}
     948
     949static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
     950                                          const struct ldb_val *in, struct ldb_val *out)
     951{
     952        struct ldb_dn *dn;
     953        int ret = -1;
     954
     955        out->length = 0;
     956        out->data = NULL;
     957
     958        dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
     959        if ( ! ldb_dn_validate(dn)) {
     960                return LDB_ERR_INVALID_DN_SYNTAX;
     961        }
     962
     963        /* By including the RMD_FLAGS of a deleted DN, we ensure it
     964         * does not casually match a not deleted DN */
     965        if (dsdb_dn_is_deleted_val(in)) {
     966                out->data = (uint8_t *)talloc_asprintf(mem_ctx,
     967                                                       "<RMD_FLAGS=%u>%s",
     968                                                       dsdb_dn_val_rmd_flags(in),
     969                                                       ldb_dn_get_casefold(dn));
     970        } else {
     971                out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
     972        }
     973
     974        if (out->data == NULL) {
     975                goto done;
     976        }
     977        out->length = strlen((char *)out->data);
     978
     979        ret = 0;
     980
     981done:
     982        talloc_free(dn);
     983
     984        return ret;
     985}
     986
     987
     988/*
     989  write a 64 bit 2-part range
     990*/
     991static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
     992                              const struct ldb_val *in, struct ldb_val *out)
     993{
     994        int64_t v;
     995        int ret;
     996        ret = val_to_int64(in, &v);
     997        if (ret != LDB_SUCCESS) {
     998                return ret;
     999        }
     1000        out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
     1001                                               (unsigned long)(v&0xFFFFFFFF),
     1002                                               (unsigned long)(v>>32));
     1003        if (out->data == NULL) {
     1004                ldb_oom(ldb);
     1005                return LDB_ERR_OPERATIONS_ERROR;
     1006        }
     1007        out->length = strlen((char *)out->data);
     1008        return LDB_SUCCESS;
     1009}
     1010
     1011/*
     1012  read a 64 bit 2-part range
     1013*/
     1014static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
     1015                              const struct ldb_val *in, struct ldb_val *out)
     1016{
     1017        unsigned long high, low;
     1018        char buf[64];
     1019
     1020        if (memchr(in->data, '-', in->length) == NULL) {
     1021                return ldb_handler_copy(ldb, mem_ctx, in, out);
     1022        }
     1023
     1024        if (in->length > sizeof(buf)-1) {
     1025                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     1026        }
     1027        strncpy(buf, (const char *)in->data, in->length);
     1028        buf[in->length] = 0;
     1029
     1030        if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
     1031                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     1032        }
     1033
     1034        out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
     1035                                               (unsigned long long)(((uint64_t)high)<<32) | (low));
     1036
     1037        if (out->data == NULL) {
     1038                ldb_oom(ldb);
     1039                return LDB_ERR_OPERATIONS_ERROR;
     1040        }
     1041        out->length = strlen((char *)out->data);
     1042        return LDB_SUCCESS;
     1043}
     1044
     1045/*
     1046  when this operator_fn is set for a syntax, the backend calls is in
     1047  preference to the comparison function. We are told the exact
     1048  comparison operation that is needed, and we can return errors
     1049 */
     1050static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
     1051                                    const struct ldb_schema_attribute *a,
     1052                                    const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
     1053{
     1054        switch (operation) {
     1055        case LDB_OP_AND:
     1056        case LDB_OP_OR:
     1057        case LDB_OP_NOT:
     1058        case LDB_OP_SUBSTRING:
     1059        case LDB_OP_APPROX:
     1060        case LDB_OP_EXTENDED:
     1061                /* handled in the backends */
     1062                return LDB_ERR_INAPPROPRIATE_MATCHING;
     1063
     1064        case LDB_OP_GREATER:
     1065        case LDB_OP_LESS:
     1066        case LDB_OP_EQUALITY:
     1067        {
     1068                TALLOC_CTX *tmp_ctx = talloc_new(ldb);
     1069                int ret;
     1070                if (tmp_ctx == NULL) {
     1071                        return ldb_oom(ldb);
     1072                }
     1073                ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
     1074                talloc_free(tmp_ctx);
     1075                if (operation == LDB_OP_GREATER) {
     1076                        *matched = (ret > 0);
     1077                } else if (operation == LDB_OP_LESS) {
     1078                        *matched = (ret < 0);
     1079                } else {
     1080                        *matched = (ret == 0);
     1081                }
     1082                return LDB_SUCCESS;
     1083        }
     1084
     1085        case LDB_OP_PRESENT:
     1086                *matched = true;
     1087                return LDB_SUCCESS;
     1088        }
     1089
     1090        /* we shouldn't get here */
     1091        return LDB_ERR_INAPPROPRIATE_MATCHING;
     1092}
     1093
     1094/*
     1095  special operation for DNs, to take account of the RMD_FLAGS deleted bit
     1096 */
     1097static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
     1098                                    const struct ldb_schema_attribute *a,
     1099                                    const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
     1100{
     1101        if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
     1102                /* If the DN is deleted, then we can't search for it */
     1103                *matched = false;
     1104                return LDB_SUCCESS;
     1105        }
     1106        return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
     1107}
     1108
    7721109
    7731110static const struct ldb_schema_syntax samba_syntaxes[] = {
     
    7771114                .ldif_write_fn    = ldif_write_objectSid,
    7781115                .canonicalise_fn  = ldif_canonicalise_objectSid,
    779                 .comparison_fn    = ldif_comparison_objectSid
     1116                .comparison_fn    = ldif_comparison_objectSid,
     1117                .operator_fn      = samba_syntax_operator_fn
    7801118        },{
    7811119                .name             = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
     
    7831121                .ldif_write_fn    = ldif_write_ntSecurityDescriptor,
    7841122                .canonicalise_fn  = ldb_handler_copy,
    785                 .comparison_fn    = ldb_comparison_binary
     1123                .comparison_fn    = ldb_comparison_binary,
     1124                .operator_fn      = samba_syntax_operator_fn
    7861125        },{
    7871126                .name             = LDB_SYNTAX_SAMBA_GUID,
     
    7891128                .ldif_write_fn    = ldif_write_objectGUID,
    7901129                .canonicalise_fn  = ldif_canonicalise_objectGUID,
    791                 .comparison_fn    = ldif_comparison_objectGUID
     1130                .comparison_fn    = ldif_comparison_objectGUID,
     1131                .operator_fn      = samba_syntax_operator_fn
    7921132        },{
    7931133                .name             = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
     
    7951135                .ldif_write_fn    = ldb_handler_copy,
    7961136                .canonicalise_fn  = ldif_canonicalise_objectCategory,
    797                 .comparison_fn    = ldif_comparison_objectCategory
     1137                .comparison_fn    = ldif_comparison_objectCategory,
     1138                .operator_fn      = samba_syntax_operator_fn
     1139        },{
     1140                .name             = LDB_SYNTAX_SAMBA_SCHEMAINFO,
     1141                .ldif_read_fn     = ldb_handler_copy,
     1142                .ldif_write_fn    = ldif_write_schemaInfo,
     1143                .canonicalise_fn  = ldb_handler_copy,
     1144                .comparison_fn    = ldb_comparison_binary,
     1145                .operator_fn      = samba_syntax_operator_fn
    7981146        },{
    7991147                .name             = LDB_SYNTAX_SAMBA_PREFIX_MAP,
     
    8011149                .ldif_write_fn    = ldif_write_prefixMap,
    8021150                .canonicalise_fn  = ldif_canonicalise_prefixMap,
    803                 .comparison_fn    = ldif_comparison_prefixMap
     1151                .comparison_fn    = ldif_comparison_prefixMap,
     1152                .operator_fn      = samba_syntax_operator_fn
    8041153        },{
    8051154                .name             = LDB_SYNTAX_SAMBA_INT32,
     
    8071156                .ldif_write_fn    = ldb_handler_copy,
    8081157                .canonicalise_fn  = ldif_canonicalise_int32,
    809                 .comparison_fn    = ldif_comparison_int32
     1158                .comparison_fn    = ldif_comparison_int32,
     1159                .operator_fn      = samba_syntax_operator_fn
    8101160        },{
    8111161                .name             = LDB_SYNTAX_SAMBA_REPSFROMTO,
     
    8131163                .ldif_write_fn    = ldif_write_repsFromTo,
    8141164                .canonicalise_fn  = ldb_handler_copy,
    815                 .comparison_fn    = ldb_comparison_binary
     1165                .comparison_fn    = ldb_comparison_binary,
     1166                .operator_fn      = samba_syntax_operator_fn
    8161167        },{
    8171168                .name             = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
     
    8191170                .ldif_write_fn    = ldif_write_replPropertyMetaData,
    8201171                .canonicalise_fn  = ldb_handler_copy,
    821                 .comparison_fn    = ldb_comparison_binary
     1172                .comparison_fn    = ldb_comparison_binary,
     1173                .operator_fn      = samba_syntax_operator_fn
    8221174        },{
    8231175                .name             = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
     
    8251177                .ldif_write_fn    = ldif_write_replUpToDateVector,
    8261178                .canonicalise_fn  = ldb_handler_copy,
    827                 .comparison_fn    = ldb_comparison_binary
    828         },
     1179                .comparison_fn    = ldb_comparison_binary,
     1180                .operator_fn      = samba_syntax_operator_fn
     1181        },{
     1182                .name             = DSDB_SYNTAX_BINARY_DN,
     1183                .ldif_read_fn     = ldb_handler_copy,
     1184                .ldif_write_fn    = ldb_handler_copy,
     1185                .canonicalise_fn  = dsdb_dn_binary_canonicalise,
     1186                .comparison_fn    = dsdb_dn_binary_comparison,
     1187                .operator_fn      = samba_syntax_operator_fn
     1188        },{
     1189                .name             = DSDB_SYNTAX_STRING_DN,
     1190                .ldif_read_fn     = ldb_handler_copy,
     1191                .ldif_write_fn    = ldb_handler_copy,
     1192                .canonicalise_fn  = dsdb_dn_string_canonicalise,
     1193                .comparison_fn    = dsdb_dn_string_comparison,
     1194                .operator_fn      = samba_syntax_operator_fn
     1195        },{
     1196                .name             = LDB_SYNTAX_DN,
     1197                .ldif_read_fn     = ldb_handler_copy,
     1198                .ldif_write_fn    = ldb_handler_copy,
     1199                .canonicalise_fn  = samba_ldb_dn_link_canonicalise,
     1200                .comparison_fn    = samba_ldb_dn_link_comparison,
     1201                .operator_fn      = samba_syntax_operator_dn
     1202        },{
     1203                .name             = LDB_SYNTAX_SAMBA_RANGE64,
     1204                .ldif_read_fn     = ldif_read_range64,
     1205                .ldif_write_fn    = ldif_write_range64,
     1206                .canonicalise_fn  = ldif_canonicalise_int64,
     1207                .comparison_fn    = ldif_comparison_int64,
     1208                .operator_fn      = samba_syntax_operator_fn
     1209        },{
     1210                .name             = LDB_SYNTAX_SAMBA_DNSRECORD,
     1211                .ldif_read_fn     = ldb_handler_copy,
     1212                .ldif_write_fn    = ldif_write_dnsRecord,
     1213                .canonicalise_fn  = ldb_handler_copy,
     1214                .comparison_fn    = ldb_comparison_binary,
     1215                .operator_fn      = samba_syntax_operator_fn
     1216        },{
     1217                .name             = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
     1218                .ldif_read_fn     = ldb_handler_copy,
     1219                .ldif_write_fn    = ldif_write_supplementalCredentialsBlob,
     1220                .canonicalise_fn  = ldb_handler_copy,
     1221                .comparison_fn    = ldb_comparison_binary,
     1222                .operator_fn      = samba_syntax_operator_fn
     1223        }
    8291224};
    8301225
     
    8421237        },{
    8431238                .name             = "WKGUID",
     1239                .read_fn          = ldb_handler_copy,
     1240                .write_clear_fn   = ldb_handler_copy,
     1241                .write_hex_fn     = ldb_handler_copy
     1242        },{
     1243                .name             = "RMD_INVOCID",
     1244                .read_fn          = extended_dn_read_GUID,
     1245                .write_clear_fn   = ldif_write_objectGUID,
     1246                .write_hex_fn     = extended_dn_write_hex
     1247        },{
     1248                .name             = "RMD_FLAGS",
     1249                .read_fn          = ldb_handler_copy,
     1250                .write_clear_fn   = ldb_handler_copy,
     1251                .write_hex_fn     = ldb_handler_copy
     1252        },{
     1253                .name             = "RMD_ADDTIME",
     1254                .read_fn          = ldb_handler_copy,
     1255                .write_clear_fn   = ldb_handler_copy,
     1256                .write_hex_fn     = ldb_handler_copy
     1257        },{
     1258                .name             = "RMD_CHANGETIME",
     1259                .read_fn          = ldb_handler_copy,
     1260                .write_clear_fn   = ldb_handler_copy,
     1261                .write_hex_fn     = ldb_handler_copy
     1262        },{
     1263                .name             = "RMD_LOCAL_USN",
     1264                .read_fn          = ldb_handler_copy,
     1265                .write_clear_fn   = ldb_handler_copy,
     1266                .write_hex_fn     = ldb_handler_copy
     1267        },{
     1268                .name             = "RMD_ORIGINATING_USN",
     1269                .read_fn          = ldb_handler_copy,
     1270                .write_clear_fn   = ldb_handler_copy,
     1271                .write_hex_fn     = ldb_handler_copy
     1272        },{
     1273                .name             = "RMD_VERSION",
    8441274                .read_fn          = ldb_handler_copy,
    8451275                .write_clear_fn   = ldb_handler_copy,
     
    8551285        { "objectSid",                  LDB_SYNTAX_SAMBA_SID },
    8561286        { "securityIdentifier",         LDB_SYNTAX_SAMBA_SID },
     1287        { "tokenGroups",                LDB_SYNTAX_SAMBA_SID },
    8571288        { "ntSecurityDescriptor",       LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
    858         { "objectGUID",                 LDB_SYNTAX_SAMBA_GUID },
    859         { "invocationId",               LDB_SYNTAX_SAMBA_GUID },
    860         { "schemaIDGUID",               LDB_SYNTAX_SAMBA_GUID },
    861         { "attributeSecurityGUID",      LDB_SYNTAX_SAMBA_GUID },
    862         { "parentGUID",                 LDB_SYNTAX_SAMBA_GUID },
    863         { "siteGUID",                   LDB_SYNTAX_SAMBA_GUID },
    864         { "pKTGUID",                    LDB_SYNTAX_SAMBA_GUID },
    865         { "fRSVersionGUID",             LDB_SYNTAX_SAMBA_GUID },
    866         { "fRSReplicaSetGUID",          LDB_SYNTAX_SAMBA_GUID },
    867         { "netbootGUID",                LDB_SYNTAX_SAMBA_GUID },
     1289        { "oMSyntax",                   LDB_SYNTAX_SAMBA_INT32 },
    8681290        { "objectCategory",             LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
     1291        { "schemaInfo",                 LDB_SYNTAX_SAMBA_SCHEMAINFO },
    8691292        { "prefixMap",                  LDB_SYNTAX_SAMBA_PREFIX_MAP },
    8701293        { "repsFrom",                   LDB_SYNTAX_SAMBA_REPSFROMTO },
     
    8721295        { "replPropertyMetaData",       LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
    8731296        { "replUpToDateVector",         LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
     1297        { "rIDAllocationPool",          LDB_SYNTAX_SAMBA_RANGE64 },
     1298        { "rIDPreviousAllocationPool",  LDB_SYNTAX_SAMBA_RANGE64 },
     1299        { "rIDAvailablePool",           LDB_SYNTAX_SAMBA_RANGE64 },
     1300
     1301        /*
     1302         * these are extracted by searching
     1303         * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
     1304         */
     1305        { "attributeSecurityGUID",              LDB_SYNTAX_SAMBA_GUID },
     1306        { "categoryId",                         LDB_SYNTAX_SAMBA_GUID },
     1307        { "controlAccessRights",                LDB_SYNTAX_SAMBA_GUID },
     1308        { "currMachineId",                      LDB_SYNTAX_SAMBA_GUID },
     1309        { "fRSReplicaSetGUID",                  LDB_SYNTAX_SAMBA_GUID },
     1310        { "fRSVersionGUID",                     LDB_SYNTAX_SAMBA_GUID },
     1311        { "implementedCategories",              LDB_SYNTAX_SAMBA_GUID },
     1312        { "msDS-AzObjectGuid",                  LDB_SYNTAX_SAMBA_GUID },
     1313        { "msDFSR-ContentSetGuid",              LDB_SYNTAX_SAMBA_GUID },
     1314        { "msDFSR-ReplicationGroupGuid",        LDB_SYNTAX_SAMBA_GUID },
     1315        { "mSMQDigests",                        LDB_SYNTAX_SAMBA_GUID },
     1316        { "mSMQOwnerID",                        LDB_SYNTAX_SAMBA_GUID },
     1317        { "mSMQQMID",                           LDB_SYNTAX_SAMBA_GUID },
     1318        { "mSMQQueueType",                      LDB_SYNTAX_SAMBA_GUID },
     1319        { "mSMQSites",                          LDB_SYNTAX_SAMBA_GUID },
     1320        { "netbootGUID",                        LDB_SYNTAX_SAMBA_GUID },
     1321        { "objectGUID",                         LDB_SYNTAX_SAMBA_GUID },
     1322        { "pKTGuid",                            LDB_SYNTAX_SAMBA_GUID },
     1323        { "requiredCategories",                 LDB_SYNTAX_SAMBA_GUID },
     1324        { "schemaIDGUID",                       LDB_SYNTAX_SAMBA_GUID },
     1325        { "siteGUID",                           LDB_SYNTAX_SAMBA_GUID },
     1326        { "msDFS-GenerationGUIDv2",             LDB_SYNTAX_SAMBA_GUID },
     1327        { "msDFS-LinkIdentityGUIDv2",           LDB_SYNTAX_SAMBA_GUID },
     1328        { "msDFS-NamespaceIdentityGUIDv2",      LDB_SYNTAX_SAMBA_GUID },
     1329
     1330        /*
     1331         * these are known to be GUIDs
     1332         */
     1333        { "invocationId",                       LDB_SYNTAX_SAMBA_GUID },
     1334        { "parentGUID",                         LDB_SYNTAX_SAMBA_GUID },
     1335        { "msDS-OptionalFeatureGUID",           LDB_SYNTAX_SAMBA_GUID },
     1336
     1337        /* These NDR encoded things we want to be able to read with --show-binary */
     1338        { "dnsRecord",                          LDB_SYNTAX_SAMBA_DNSRECORD },
     1339        { "supplementalCredentials",            LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS}
    8741340};
    8751341
    8761342const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
    8771343{
    878         uint32_t j;
     1344        unsigned int j;
    8791345        const struct ldb_schema_syntax *s = NULL;
    8801346       
     
    8901356const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
    8911357{
    892         uint32_t j;
     1358        unsigned int j;
    8931359        const struct ldb_schema_syntax *s = NULL;
    8941360
     
    9081374int ldb_register_samba_handlers(struct ldb_context *ldb)
    9091375{
    910         uint32_t i;
     1376        unsigned int i;
     1377        int ret;
     1378
     1379        if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
     1380                return LDB_SUCCESS;
     1381        }
    9111382
    9121383        for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
    913                 int ret;
    9141384                const struct ldb_schema_syntax *s = NULL;
    9151385
     
    9211391
    9221392                if (!s) {
    923                         return -1;
     1393                        return LDB_ERR_OPERATIONS_ERROR;
    9241394                }
    9251395
     
    9311401
    9321402        for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
    933                 int ret;
    9341403                ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
    9351404                if (ret != LDB_SUCCESS) {
     
    9371406                }
    9381407
    939                
     1408        }
     1409
     1410        ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
     1411        if (ret != LDB_SUCCESS) {
     1412                return ret;
    9401413        }
    9411414
  • trunk/server/source4/lib/ldb-samba/ldif_handlers.h

    r414 r745  
    66#define LDB_SYNTAX_SAMBA_GUID                   "LDB_SYNTAX_SAMBA_GUID"
    77#define LDB_SYNTAX_SAMBA_OBJECT_CATEGORY        "LDB_SYNTAX_SAMBA_OBJECT_CATEGORY"
     8#define LDB_SYNTAX_SAMBA_SCHEMAINFO             "LDB_SYNTAX_SAMBA_SCHEMAINFO"
    89#define LDB_SYNTAX_SAMBA_PREFIX_MAP             "LDB_SYNTAX_SAMBA_PREFIX_MAP"
    910#define LDB_SYNTAX_SAMBA_INT32                  "LDB_SYNTAX_SAMBA_INT32"
     
    1112#define LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA   "LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA"
    1213#define LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR     "LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR"
    13 
     14#define LDB_SYNTAX_SAMBA_RANGE64                "LDB_SYNTAX_SAMBA_RANGE64"
     15#define LDB_SYNTAX_SAMBA_DNSRECORD              "LDB_SYNTAX_SAMBA_DNSRECORD"
     16#define LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS "LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS"
    1417#include "lib/ldb-samba/ldif_handlers_proto.h"
    1518
  • trunk/server/source4/lib/ldb/common/attrib_handlers.c

    r414 r745  
    33
    44   Copyright (C) Andrew Tridgell  2005
     5   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2009
    56
    67     ** NOTE! The following LGPL license applies to the ldb
     
    5556{
    5657        char *s, *t;
    57         int l;
     58        size_t l;
    5859
    5960        if (!in || !out || !(in->data)) {
     
    100101}
    101102
     103/* length limited conversion of a ldb_val to a int32_t */
     104static int val_to_int64(const struct ldb_val *in, int64_t *v)
     105{
     106        char *end;
     107        char buf[64];
     108
     109        /* make sure we don't read past the end of the data */
     110        if (in->length > sizeof(buf)-1) {
     111                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     112        }
     113        strncpy(buf, (char *)in->data, in->length);
     114        buf[in->length] = 0;
     115
     116        /* We've to use "strtoll" here to have the intended overflows.
     117         * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
     118        *v = (int64_t) strtoll(buf, &end, 0);
     119        if (*end != 0) {
     120                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     121        }
     122        return LDB_SUCCESS;
     123}
    102124
    103125
     
    109131                                    const struct ldb_val *in, struct ldb_val *out)
    110132{
    111         char *end;
    112         long long i = strtoll((char *)in->data, &end, 0);
    113         if (*end != 0) {
    114                 return -1;
    115         }
    116         out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lld", i);
     133        int64_t i;
     134        int ret;
     135
     136        ret = val_to_int64(in, &i);
     137        if (ret != LDB_SUCCESS) {
     138                return ret;
     139        }
     140        out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
    117141        if (out->data == NULL) {
    118                 return -1;
     142                ldb_oom(ldb);
     143                return LDB_ERR_OPERATIONS_ERROR;
    119144        }
    120145        out->length = strlen((char *)out->data);
     
    128153                                  const struct ldb_val *v1, const struct ldb_val *v2)
    129154{
    130         return strtoll((char *)v1->data, NULL, 0) - strtoll((char *)v2->data, NULL, 0);
     155        int64_t i1=0, i2=0;
     156        val_to_int64(v1, &i1);
     157        val_to_int64(v2, &i2);
     158        if (i1 == i2) return 0;
     159        return i1 > i2? 1 : -1;
    131160}
    132161
     
    241270                talloc_free(b1);
    242271                talloc_free(b2);
    243                 if (memcmp(s1, s2, MIN(n1, n2)) == 0) {
     272                ret = memcmp(s1, s2, MIN(n1, n2));
     273                if (ret == 0) {
    244274                        if (n1 == n2) return 0;
    245275                        if (n1 > n2) {
     
    249279                        }
    250280                }
     281                return ret;
    251282        }
    252283
     
    338369                                  const struct ldb_val *v1, const struct ldb_val *v2)
    339370{
    340         time_t t1, t2;
    341         t1 = ldb_string_to_time((char *)v1->data);
    342         t2 = ldb_string_to_time((char *)v2->data);
    343         return (int)t2 - (int)t1;
     371        time_t t1=0, t2=0;
     372        ldb_val_to_time(v1, &t1);
     373        ldb_val_to_time(v2, &t2);
     374        if (t1 == t2) return 0;
     375        return t1 > t2? 1 : -1;
    344376}
    345377
     
    350382                                    const struct ldb_val *in, struct ldb_val *out)
    351383{
    352         time_t t = ldb_string_to_time((char *)in->data);
     384        time_t t;
     385        int ret;
     386        ret = ldb_val_to_time(in, &t);
     387        if (ret != LDB_SUCCESS) {
     388                return ret;
     389        }
    353390        out->data = (uint8_t *)ldb_timestring(mem_ctx, t);
    354391        if (out->data == NULL) {
    355                 return -1;
     392                ldb_oom(ldb);
     393                return LDB_ERR_OPERATIONS_ERROR;
    356394        }
    357395        out->length = strlen((char *)out->data);
     
    421459                                                            const char *syntax)
    422460{
    423         int i;
     461        unsigned int i;
    424462        unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]);
    425463        /* TODO: should be replaced with a binary search */
     
    431469        return NULL;
    432470}
     471
     472int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx,
     473                       ldb_attr_handler_t canonicalise_fn,
     474                       const struct ldb_val *v1,
     475                       const struct ldb_val *v2)
     476{
     477        int ret, ret1, ret2;
     478        struct ldb_val v1_canon, v2_canon;
     479        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     480
     481        /* I could try and bail if tmp_ctx was NULL, but what return
     482         * value would I use?
     483         *
     484         * It seems easier to continue on the NULL context
     485         */
     486        ret1 = canonicalise_fn(ldb, tmp_ctx, v1, &v1_canon);
     487        ret2 = canonicalise_fn(ldb, tmp_ctx, v2, &v2_canon);
     488
     489        if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
     490                ret = ldb_comparison_binary(ldb, mem_ctx, &v1_canon, &v2_canon);
     491        } else {
     492                ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
     493        }
     494        talloc_free(tmp_ctx);
     495        return ret;
     496}
  • trunk/server/source4/lib/ldb/common/ldb.c

    r414 r745  
    3535#define TEVENT_DEPRECATED 1
    3636#include "ldb_private.h"
     37#include "ldb.h"
    3738
    3839static int ldb_context_destructor(void *ptr)
     
    9293        struct ldb_context *ldb;
    9394        int ret;
     95        const char *modules_path = getenv("LDB_MODULES_PATH");
     96
     97        if (modules_path == NULL) {
     98                modules_path = LDB_MODULESDIR;
     99        }
     100
     101        ret = ldb_modules_load(modules_path, LDB_VERSION);
     102        if (ret != LDB_SUCCESS) {
     103                return NULL;
     104        }
    94105
    95106        ldb = talloc_zero(mem_ctx, struct ldb_context);
    96         /* FIXME: Hack a new event context so that CMD line utilities work
    97          * until we have them all converted */
     107        /* A new event context so that callers who don't want ldb
     108         * operating on thier global event context can work without
     109         * having to provide their own private one explicitly */
    98110        if (ev_ctx == NULL) {
    99                 ev_ctx = tevent_context_init(talloc_autofree_context());
     111                ev_ctx = tevent_context_init(ldb);
    100112                tevent_set_debug(ev_ctx, ldb_tevent_debug, ldb);
    101113                tevent_loop_allow_nesting(ev_ctx);
     
    103115
    104116        ret = ldb_setup_wellknown_attributes(ldb);
    105         if (ret != 0) {
     117        if (ret != LDB_SUCCESS) {
    106118                talloc_free(ldb);
    107119                return NULL;
     
    218230{
    219231        int ret;
    220         const char *url2;
     232        char *url2;
    221233        /* We seem to need to do this here, or else some utilities don't
    222234         * get ldb backends */
     
    229241                return LDB_ERR_OPERATIONS_ERROR;
    230242        }
    231         ret = ldb_set_opaque(ldb, "ldb_url", talloc_strdup(ldb, url2));
     243        ret = ldb_set_opaque(ldb, "ldb_url", url2);
    232244        if (ret != LDB_SUCCESS) {
    233245                return ret;
    234246        }
    235247
    236         ret = ldb_connect_backend(ldb, url, options, &ldb->modules);
     248        ret = ldb_module_connect_backend(ldb, url, options, &ldb->modules);
    237249        if (ret != LDB_SUCCESS) {
    238250                return ret;
     
    286298}
    287299
     300
     301
     302/*
     303  set an ldb error based on file:line
     304*/
     305int ldb_error_at(struct ldb_context *ldb, int ecode,
     306                 const char *reason, const char *file, int line)
     307{
     308        if (reason == NULL) {
     309                reason = ldb_strerror(ecode);
     310        }
     311        ldb_asprintf_errstring(ldb, "%s at %s:%d", reason, file, line);
     312        return ecode;
     313}
     314
     315
    288316#define FIRST_OP_NOERR(ldb, op) do { \
    289317        module = ldb->modules;                                  \
    290318        while (module && module->ops->op == NULL) module = module->next; \
     319        if ((ldb->flags & LDB_FLG_ENABLE_TRACING) && module) { \
     320                ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_trace_request: (%s)->" #op, \
     321                          module->ops->name);                           \
     322        }                                                               \
    291323} while (0)
    292324
     
    336368                }
    337369        }
     370        if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
     371                ldb_debug(module->ldb, LDB_DEBUG_TRACE, "start ldb transaction error: %s",
     372                          ldb_errstring(module->ldb));                         
     373        }
    338374        return status;
    339375}
     
    375411                /* if a module fails the prepare then we need
    376412                   to call the end transaction for everyone */
    377                 FIRST_OP(ldb, end_transaction);
    378                 module->ops->end_transaction(module);
     413                FIRST_OP(ldb, del_transaction);
     414                module->ops->del_transaction(module);
    379415                if (ldb->err_string == NULL) {
    380416                        /* no error string was setup by the backend */
     
    383419                                               ldb_strerror(status),
    384420                                               status);
     421                }
     422                if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
     423                        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "prepare commit transaction error: %s",
     424                                  ldb_errstring(module->ldb));                         
    385425                }
    386426        }
     
    433473                                status);
    434474                }
     475                if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
     476                        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "commit ldb transaction error: %s",
     477                                  ldb_errstring(module->ldb));                         
     478                }
    435479                /* cancel the transaction */
    436480                FIRST_OP(ldb, del_transaction);
     
    478522                                status);
    479523                }
     524                if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
     525                        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "cancel ldb transaction error: %s",
     526                                  ldb_errstring(module->ldb));                         
     527                }
    480528        }
    481529        return status;
    482530}
     531
     532/*
     533  cancel a transaction with no error if no transaction is pending
     534  used when we fork() to clear any parent transactions
     535*/
     536int ldb_transaction_cancel_noerr(struct ldb_context *ldb)
     537{
     538        if (ldb->transaction_active > 0) {
     539                return ldb_transaction_cancel(ldb);
     540        }
     541        return LDB_SUCCESS;
     542}
     543
    483544
    484545/* autostarts a transacion if none active */
     
    633694{
    634695        TALLOC_CTX *tmp_ctx = talloc_new(req);
    635         int i;
     696        unsigned int i;
    636697
    637698        switch (req->operation) {
     
    706767        } else {
    707768                for (i=0; req->controls && req->controls[i]; i++) {
    708                         ldb_debug_add(ldb, " control: %s  crit:%u  data:%s\n",
    709                                       req->controls[i]->oid,
    710                                       req->controls[i]->critical,
    711                                       req->controls[i]->data?"yes":"no");
     769                        if (req->controls[i]->oid) {
     770                                ldb_debug_add(ldb, " control: %s  crit:%u  data:%s\n",
     771                                              req->controls[i]->oid,
     772                                              req->controls[i]->critical,
     773                                              req->controls[i]->data?"yes":"no");
     774                        }
    712775                }
    713776        }
     
    716779
    717780        talloc_free(tmp_ctx);
     781}
     782
     783/*
     784  check that the element flags don't have any internal bits set
     785 */
     786static int ldb_msg_check_element_flags(struct ldb_context *ldb,
     787                                       const struct ldb_message *message)
     788{
     789        unsigned i;
     790        for (i=0; i<message->num_elements; i++) {
     791                if (message->elements[i].flags & LDB_FLAG_INTERNAL_MASK) {
     792                        ldb_asprintf_errstring(ldb, "Invalid element flags 0x%08x on element %s in %s\n",
     793                                               message->elements[i].flags, message->elements[i].name,
     794                                               ldb_dn_get_linearized(message->dn));
     795                        return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
     796                }
     797        }
     798        return LDB_SUCCESS;
    718799}
    719800
     
    743824        switch (req->operation) {
    744825        case LDB_SEARCH:
     826                /* due to "ldb_build_search_req" base DN always != NULL */
     827                if (!ldb_dn_validate(req->op.search.base)) {
     828                        ldb_asprintf_errstring(ldb, "ldb_search: invalid basedn '%s'",
     829                                               ldb_dn_get_linearized(req->op.search.base));
     830                        return LDB_ERR_INVALID_DN_SYNTAX;
     831                }
    745832                FIRST_OP(ldb, search);
    746833                ret = module->ops->search(module, req);
    747834                break;
    748835        case LDB_ADD:
     836                if (!ldb_dn_validate(req->op.add.message->dn)) {
     837                        ldb_asprintf_errstring(ldb, "ldb_add: invalid dn '%s'",
     838                                               ldb_dn_get_linearized(req->op.add.message->dn));
     839                        return LDB_ERR_INVALID_DN_SYNTAX;
     840                }
     841                /*
     842                 * we have to normalize here, as so many places
     843                 * in modules and backends assume we don't have two
     844                 * elements with the same name
     845                 */
     846                ret = ldb_msg_normalize(ldb, req, req->op.add.message,
     847                                        discard_const(&req->op.add.message));
     848                if (ret != LDB_SUCCESS) {
     849                        ldb_oom(ldb);
     850                        return LDB_ERR_OPERATIONS_ERROR;
     851                }
    749852                FIRST_OP(ldb, add);
     853                ret = ldb_msg_check_element_flags(ldb, req->op.add.message);
     854                if (ret != LDB_SUCCESS) {
     855                        return ret;
     856                }
    750857                ret = module->ops->add(module, req);
    751858                break;
    752859        case LDB_MODIFY:
     860                if (!ldb_dn_validate(req->op.mod.message->dn)) {
     861                        ldb_asprintf_errstring(ldb, "ldb_modify: invalid dn '%s'",
     862                                               ldb_dn_get_linearized(req->op.mod.message->dn));
     863                        return LDB_ERR_INVALID_DN_SYNTAX;
     864                }
    753865                FIRST_OP(ldb, modify);
     866                ret = ldb_msg_check_element_flags(ldb, req->op.mod.message);
     867                if (ret != LDB_SUCCESS) {
     868                        return ret;
     869                }
    754870                ret = module->ops->modify(module, req);
    755871                break;
    756872        case LDB_DELETE:
     873                if (!ldb_dn_validate(req->op.del.dn)) {
     874                        ldb_asprintf_errstring(ldb, "ldb_delete: invalid dn '%s'",
     875                                               ldb_dn_get_linearized(req->op.del.dn));
     876                        return LDB_ERR_INVALID_DN_SYNTAX;
     877                }
    757878                FIRST_OP(ldb, del);
    758879                ret = module->ops->del(module, req);
    759880                break;
    760881        case LDB_RENAME:
     882                if (!ldb_dn_validate(req->op.rename.olddn)) {
     883                        ldb_asprintf_errstring(ldb, "ldb_rename: invalid olddn '%s'",
     884                                               ldb_dn_get_linearized(req->op.rename.olddn));
     885                        return LDB_ERR_INVALID_DN_SYNTAX;
     886                }
     887                if (!ldb_dn_validate(req->op.rename.newdn)) {
     888                        ldb_asprintf_errstring(ldb, "ldb_rename: invalid newdn '%s'",
     889                                               ldb_dn_get_linearized(req->op.rename.newdn));
     890                        return LDB_ERR_INVALID_DN_SYNTAX;
     891                }
    761892                FIRST_OP(ldb, rename);
    762893                ret = module->ops->rename(module, req);
     
    794925{
    795926        struct ldb_result *res;
    796         int n;
     927        unsigned int n;
    797928
    798929        res = talloc_get_type(req->context, struct ldb_result);
     
    852983}
    853984
    854 int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares)
    855 {
     985int ldb_modify_default_callback(struct ldb_request *req, struct ldb_reply *ares)
     986{
     987        struct ldb_result *res;
     988        unsigned int n;
    856989        int ret;
     990
     991        res = talloc_get_type(req->context, struct ldb_result);
    857992
    858993        if (!ares) {
     
    8661001        }
    8671002
     1003        switch (ares->type) {
     1004        case LDB_REPLY_REFERRAL:
     1005                if (res->refs) {
     1006                        for (n = 0; res->refs[n]; n++) /*noop*/ ;
     1007                } else {
     1008                        n = 0;
     1009                }
     1010
     1011                res->refs = talloc_realloc(res, res->refs, char *, n + 2);
     1012                if (! res->refs) {
     1013                        return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     1014                }
     1015
     1016                res->refs[n] = talloc_move(res->refs, &ares->referral);
     1017                res->refs[n + 1] = NULL;
     1018                break;
     1019
     1020        case LDB_REPLY_DONE:
     1021                talloc_free(ares);
     1022                return ldb_request_done(req, LDB_SUCCESS);
     1023        default:
     1024                talloc_free(ares);
     1025                ldb_set_errstring(req->handle->ldb, "Invalid reply type!");
     1026                return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     1027        }
     1028
     1029        talloc_free(ares);
     1030        return ldb_request_done(req, LDB_SUCCESS);
     1031}
     1032
     1033int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares)
     1034{
     1035        int ret;
     1036
     1037        if (!ares) {
     1038                return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     1039        }
     1040
     1041        if (ares->error != LDB_SUCCESS) {
     1042                ret = ares->error;
     1043                talloc_free(ares);
     1044                return ldb_request_done(req, ret);
     1045        }
     1046
    8681047        if (ares->type != LDB_REPLY_DONE) {
    8691048                talloc_free(ares);
     
    8781057int ldb_build_search_req_ex(struct ldb_request **ret_req,
    8791058                        struct ldb_context *ldb,
    880                         void *mem_ctx,
     1059                        TALLOC_CTX *mem_ctx,
    8811060                        struct ldb_dn *base,
    8821061                        enum ldb_scope scope,
     
    9281107        if (parent) {
    9291108                req->handle->nesting++;
     1109                req->handle->parent = parent;
     1110                req->handle->flags = parent->handle->flags;
    9301111        }
    9311112
     
    9361117int ldb_build_search_req(struct ldb_request **ret_req,
    9371118                        struct ldb_context *ldb,
    938                         void *mem_ctx,
     1119                        TALLOC_CTX *mem_ctx,
    9391120                        struct ldb_dn *base,
    9401121                        enum ldb_scope scope,
     
    9661147int ldb_build_add_req(struct ldb_request **ret_req,
    9671148                        struct ldb_context *ldb,
    968                         void *mem_ctx,
     1149                        TALLOC_CTX *mem_ctx,
    9691150                        const struct ldb_message *message,
    9701151                        struct ldb_control **controls,
     
    9991180        if (parent) {
    10001181                req->handle->nesting++;
     1182                req->handle->parent = parent;
     1183                req->handle->flags = parent->handle->flags;
    10011184        }
    10021185
     
    10081191int ldb_build_mod_req(struct ldb_request **ret_req,
    10091192                        struct ldb_context *ldb,
    1010                         void *mem_ctx,
     1193                        TALLOC_CTX *mem_ctx,
    10111194                        const struct ldb_message *message,
    10121195                        struct ldb_control **controls,
     
    10411224        if (parent) {
    10421225                req->handle->nesting++;
     1226                req->handle->parent = parent;
     1227                req->handle->flags = parent->handle->flags;
    10431228        }
    10441229
     
    10501235int ldb_build_del_req(struct ldb_request **ret_req,
    10511236                        struct ldb_context *ldb,
    1052                         void *mem_ctx,
     1237                        TALLOC_CTX *mem_ctx,
    10531238                        struct ldb_dn *dn,
    10541239                        struct ldb_control **controls,
     
    10831268        if (parent) {
    10841269                req->handle->nesting++;
     1270                req->handle->parent = parent;
     1271                req->handle->flags = parent->handle->flags;
    10851272        }
    10861273
     
    10921279int ldb_build_rename_req(struct ldb_request **ret_req,
    10931280                        struct ldb_context *ldb,
    1094                         void *mem_ctx,
     1281                        TALLOC_CTX *mem_ctx,
    10951282                        struct ldb_dn *olddn,
    10961283                        struct ldb_dn *newdn,
     
    11271314        if (parent) {
    11281315                req->handle->nesting++;
     1316                req->handle->parent = parent;
     1317                req->handle->flags = parent->handle->flags;
    11291318        }
    11301319
     
    11651354int ldb_build_extended_req(struct ldb_request **ret_req,
    11661355                           struct ldb_context *ldb,
    1167                            void *mem_ctx,
     1356                           TALLOC_CTX *mem_ctx,
    11681357                           const char *oid,
    11691358                           void *data,
     
    12001389        if (parent) {
    12011390                req->handle->nesting++;
     1391                req->handle->parent = parent;
     1392                req->handle->flags = parent->handle->flags;
    12021393        }
    12031394
     
    12921483                                        ldb_search_default_callback,
    12931484                                        NULL);
     1485        ldb_req_set_location(req, "ldb_search");
    12941486
    12951487        if (ret != LDB_SUCCESS) goto done;
     
    13351527                                        ldb_op_default_callback,
    13361528                                        NULL);
     1529        ldb_req_set_location(req, "ldb_add");
    13371530
    13381531        if (ret != LDB_SUCCESS) return ret;
     
    13651558                                        ldb_op_default_callback,
    13661559                                        NULL);
     1560        ldb_req_set_location(req, "ldb_modify");
    13671561
    13681562        if (ret != LDB_SUCCESS) return ret;
     
    13901584                                        ldb_op_default_callback,
    13911585                                        NULL);
     1586        ldb_req_set_location(req, "ldb_delete");
    13921587
    13931588        if (ret != LDB_SUCCESS) return ret;
     
    14161611                                        ldb_op_default_callback,
    14171612                                        NULL);
     1613        ldb_req_set_location(req, "ldb_rename");
    14181614
    14191615        if (ret != LDB_SUCCESS) return ret;
     
    16401836        ldb->flags = flags;
    16411837}
     1838
     1839
     1840/*
     1841  set the location in a ldb request. Used for debugging
     1842 */
     1843void ldb_req_set_location(struct ldb_request *req, const char *location)
     1844{
     1845        if (req && req->handle) {
     1846                req->handle->location = location;
     1847        }
     1848}
     1849
     1850/*
     1851  return the location set with dsdb_req_set_location
     1852 */
     1853const char *ldb_req_location(struct ldb_request *req)
     1854{
     1855        return req->handle->location;
     1856}
     1857
     1858/**
     1859  mark a request as untrusted. This tells the rootdse module to remove
     1860  unregistered controls
     1861 */
     1862void ldb_req_mark_untrusted(struct ldb_request *req)
     1863{
     1864        req->handle->flags |= LDB_HANDLE_FLAG_UNTRUSTED;
     1865}
     1866
     1867/**
     1868  mark a request as trusted.
     1869 */
     1870void ldb_req_mark_trusted(struct ldb_request *req)
     1871{
     1872        req->handle->flags &= ~LDB_HANDLE_FLAG_UNTRUSTED;
     1873}
     1874
     1875/**
     1876   return true is a request is untrusted
     1877 */
     1878bool ldb_req_is_untrusted(struct ldb_request *req)
     1879{
     1880        return (req->handle->flags & LDB_HANDLE_FLAG_UNTRUSTED) != 0;
     1881}
  • trunk/server/source4/lib/ldb/common/ldb_attributes.c

    r414 r745  
    5050                                         const struct ldb_schema_syntax *syntax)
    5151{
    52         int i, n;
     52        unsigned int i, n;
    5353        struct ldb_schema_attribute *a;
    5454
     
    123123        const char *name)
    124124{
    125         int i, e, b = 0, r;
     125        /* for binary search we need signed variables */
     126        unsigned int i, e, b = 0;
     127        int r;
    126128        const struct ldb_schema_attribute *def = &ldb_attribute_default;
    127129
     
    135137        e = ldb->schema.num_attributes - 1;
    136138
    137         while (b <= e) {
    138 
     139        while ((b <= e) && (e != (unsigned int) -1)) {
    139140                i = (b + e) / 2;
    140141
     
    148149                        b = i + 1;
    149150                }
    150 
    151151        }
    152152
     
    180180{
    181181        const struct ldb_schema_attribute *a;
    182         int i;
     182        ptrdiff_t i;
    183183
    184184        a = ldb_schema_attribute_by_name_internal(ldb, name);
     
    233233                { "objectClass", LDB_SYNTAX_OBJECTCLASS }
    234234        };
    235         int i;
     235        unsigned int i;
    236236        int ret;
    237237
     
    255255                               const struct ldb_dn_extended_syntax *syntax)
    256256{
    257         int n;
     257        unsigned int n;
    258258        struct ldb_dn_extended_syntax *a;
    259259
     
    285285                                                                    const char *name)
    286286{
    287         int i;
     287        unsigned int i;
    288288        for (i=0; i < ldb->schema.num_dn_extended_syntax; i++) {
    289289                if (ldb_attr_cmp(ldb->schema.dn_extended_syntax[i].name, name) == 0) {
  • trunk/server/source4/lib/ldb/common/ldb_controls.c

    r414 r745  
    3838struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid)
    3939{
    40         int i;
     40        unsigned int i;
    4141
    4242        if (req->controls != NULL) {
    4343                for (i = 0; req->controls[i]; i++) {
    44                         if (strcmp(oid, req->controls[i]->oid) == 0) {
     44                        if (req->controls[i]->oid && strcmp(oid, req->controls[i]->oid) == 0) {
    4545                                break;
    4646                        }
     
    5757struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid)
    5858{
    59         int i;
     59        unsigned int i;
    6060
    6161        if (rep->controls != NULL) {
    6262                for (i = 0; rep->controls[i]; i++) {
    63                         if (strcmp(oid, rep->controls[i]->oid) == 0) {
     63                        if (rep->controls[i]->oid && strcmp(oid, rep->controls[i]->oid) == 0) {
    6464                                break;
    6565                        }
     
    7272}
    7373
    74 /* saves the current controls list into the "saver" and replace the one in req with a new one excluding
    75 the "exclude" control */
    76 /* returns 0 on error */
    77 int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver)
     74/*
     75 * Saves the current controls list into the "saver" (can also be NULL) and
     76 * replace the one in "req" with a new one excluding the "exclude" control
     77 * (if it is NULL then the list remains the same)
     78 *
     79 * Returns 0 on error.
     80 */
     81int ldb_save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver)
    7882{
    79         struct ldb_control **lcs;
    80         int i, j;
    81 
    82         *saver = req->controls;
    83         for (i = 0; req->controls[i]; i++);
    84         if (i == 1) {
     83        struct ldb_control **lcs, **lcs_old;
     84        unsigned int i, j;
     85
     86        lcs_old = req->controls;
     87        if (saver != NULL) {
     88                *saver = lcs_old;
     89        }
     90
     91        for (i = 0; req->controls && req->controls[i]; i++);
     92        if (i == 0) {
    8593                req->controls = NULL;
    8694                return 1;
    8795        }
    8896
    89         lcs = talloc_array(req, struct ldb_control *, i);
     97        lcs = talloc_array(req, struct ldb_control *, i + 1);
    9098        if (!lcs) {
    9199                return 0;
    92100        }
    93101
    94         for (i = 0, j = 0; (*saver)[i]; i++) {
    95                 if (exclude == (*saver)[i]) continue;
    96                 lcs[j] = (*saver)[i];
     102        for (i = 0, j = 0; lcs_old[i]; i++) {
     103                if (exclude == lcs_old[i]) continue;
     104                lcs[j] = lcs_old[i];
    97105                j++;
    98106        }
    99107        lcs[j] = NULL;
    100108
    101         req->controls = lcs;
     109        req->controls = talloc_realloc(req, lcs, struct ldb_control *, j + 1);
     110        if (req->controls == NULL) {
     111                return 0;
     112        }
    102113        return 1;
    103114}
    104115
     116/*
     117 * Returns a list of controls, except the one specified with "exclude" (can
     118 * also be NULL).  Included controls become a child of returned list if they
     119 * were children of "controls_in".
     120 *
     121 * Returns NULL on error (OOM) or an empty control list.
     122 */
     123struct ldb_control **ldb_controls_except_specified(struct ldb_control **controls_in,
     124                                               TALLOC_CTX *mem_ctx,
     125                                               struct ldb_control *exclude)
     126{
     127        struct ldb_control **lcs = NULL;
     128        unsigned int i, j, n;
     129
     130        for (i = 0; controls_in && controls_in[i]; i++);
     131        if (i == 0) {
     132                return NULL;
     133        }
     134        n = i;
     135
     136        for (i = 0, j = 0; controls_in && controls_in[i]; i++) {
     137                if (exclude == controls_in[i]) continue;
     138
     139                if (!lcs) {
     140                        /* Allocate here so if we remove the only
     141                         * control, or there were no controls, we
     142                         * don't allocate at all, and just return
     143                         * NULL */
     144                        lcs = talloc_array(mem_ctx, struct ldb_control *,
     145                                           n + 1);
     146                        if (!lcs) {
     147                                return NULL;
     148                        }
     149                }
     150
     151                lcs[j] = controls_in[i];
     152                talloc_reparent(controls_in, lcs, lcs[j]);
     153                j++;
     154        }
     155        if (lcs) {
     156                lcs[j] = NULL;
     157
     158                lcs = talloc_realloc(mem_ctx, lcs, struct ldb_control *, j + 1);
     159        }
     160
     161        return lcs;
     162}
     163
    105164/* check if there's any control marked as critical in the list */
    106165/* return True if any, False if none */
    107 int check_critical_controls(struct ldb_control **controls)
     166int ldb_check_critical_controls(struct ldb_control **controls)
    108167{
    109         int i;
     168        unsigned int i;
    110169
    111170        if (controls == NULL) {
     
    123182
    124183int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data)
     184{
     185        unsigned int i, n;
     186        struct ldb_control **ctrls;
     187        struct ldb_control *ctrl;
     188
     189        for (n=0; req->controls && req->controls[n];n++) {
     190                /* having two controls of the same OID makes no sense */
     191                if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) {
     192                        return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     193                }
     194        }
     195
     196        ctrls = talloc_array(req,
     197                               struct ldb_control *,
     198                               n + 2);
     199        if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
     200
     201        for (i=0; i<n; i++) {
     202                ctrls[i] = req->controls[i];
     203        }
     204
     205        req->controls = ctrls;
     206        ctrls[n] = NULL;
     207        ctrls[n+1] = NULL;
     208
     209        ctrl = talloc(ctrls, struct ldb_control);
     210        if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
     211
     212        ctrl->oid       = talloc_strdup(ctrl, oid);
     213        if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
     214        ctrl->critical  = critical;
     215        ctrl->data      = data;
     216
     217        ctrls[n] = ctrl;
     218        return LDB_SUCCESS;
     219}
     220
     221int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data)
    125222{
    126223        unsigned n;
     
    128225        struct ldb_control *ctrl;
    129226
    130         for (n=0; req->controls && req->controls[n];) {
     227        for (n=0; ares->controls && ares->controls[n];) {
    131228                /* having two controls of the same OID makes no sense */
    132                 if (strcmp(oid, req->controls[n]->oid) == 0) {
     229                if (ares->controls[n]->oid && strcmp(oid, ares->controls[n]->oid) == 0) {
    133230                        return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
    134231                }
     
    136233        }
    137234
    138         ctrls = talloc_realloc(req, req->controls,
     235        ctrls = talloc_realloc(ares, ares->controls,
    139236                               struct ldb_control *,
    140237                               n + 2);
    141238        if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
    142         req->controls = ctrls;
     239        ares->controls = ctrls;
    143240        ctrls[n] = NULL;
    144241        ctrls[n+1] = NULL;
     
    156253}
    157254
    158 /* Parse controls from the format used on the command line and in ejs */
    159 
    160 struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings)
     255/* Add a control to the request, replacing the old one if it is already in the request */
     256int ldb_request_replace_control(struct ldb_request *req, const char *oid, bool critical, void *data)
    161257{
    162         int i;
    163         struct ldb_control **ctrl;
    164 
     258        unsigned int n;
     259        int ret;
     260
     261        ret = ldb_request_add_control(req, oid, critical, data);
     262        if (ret != LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
     263                return ret;
     264        }
     265
     266        for (n=0; req->controls[n];n++) {
     267                if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) {
     268                        req->controls[n]->critical = critical;
     269                        req->controls[n]->data = data;
     270                        return LDB_SUCCESS;
     271                }
     272        }
     273
     274        return LDB_ERR_OPERATIONS_ERROR;
     275}
     276
     277/*
     278 * Return a control as string
     279 * the project (ie. name:value1:value2:...:valuen
     280 * The string didn't include the criticity of the critical flag
     281 */
     282char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *control)
     283{
     284        char *res = NULL;
     285
     286        if (strcmp(control->oid, LDB_CONTROL_PAGED_RESULTS_OID) == 0) {
     287                struct ldb_paged_control *rep_control = talloc_get_type(control->data, struct ldb_paged_control);
     288                char *cookie;
     289
     290                cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, rep_control->cookie_len);
     291                if (cookie == NULL) {
     292                        return NULL;
     293                }
     294                if (cookie[0] != '\0') {
     295                        res = talloc_asprintf(mem_ctx, "%s:%d:%s",
     296                                                LDB_CONTROL_PAGED_RESULTS_NAME,
     297                                                control->critical,
     298                                                cookie);
     299
     300                        talloc_free(cookie);
     301                } else {
     302                        res = talloc_asprintf(mem_ctx, "%s:%d",
     303                                                LDB_CONTROL_PAGED_RESULTS_NAME,
     304                                                control->critical);
     305                }
     306                return res;
     307        }
     308
     309        if (strcmp(control->oid, LDB_CONTROL_VLV_RESP_OID) == 0) {
     310                struct ldb_vlv_resp_control *rep_control = talloc_get_type(control->data,
     311                                                                struct ldb_vlv_resp_control);
     312
     313                res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%d:%d:%s",
     314                                                LDB_CONTROL_VLV_RESP_NAME,
     315                                                control->critical,
     316                                                rep_control->targetPosition,
     317                                                rep_control->contentCount,
     318                                                rep_control->vlv_result,
     319                                                rep_control->ctxid_len,
     320                                                rep_control->contextId);
     321
     322                return res;
     323        }
     324
     325        if (strcmp(control->oid, LDB_CONTROL_SORT_RESP_OID) == 0) {
     326                struct ldb_sort_resp_control *rep_control = talloc_get_type(control->data,
     327                                                                struct ldb_sort_resp_control);
     328
     329                res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s",
     330                                        LDB_CONTROL_SORT_RESP_NAME,
     331                                        control->critical,
     332                                        rep_control->result,
     333                                        rep_control->attr_desc);
     334
     335                return res;
     336        }
     337
     338        if (strcmp(control->oid, LDB_CONTROL_ASQ_OID) == 0) {
     339                struct ldb_asq_control *rep_control = talloc_get_type(control->data,
     340                                                                struct ldb_asq_control);
     341
     342                res = talloc_asprintf(mem_ctx, "%s:%d:%d",
     343                                        LDB_CONTROL_SORT_RESP_NAME,
     344                                        control->critical,
     345                                        rep_control->result);
     346
     347                return res;
     348        }
     349
     350        if (strcmp(control->oid, LDB_CONTROL_DIRSYNC_OID) == 0) {
     351                char *cookie;
     352                struct ldb_dirsync_control *rep_control = talloc_get_type(control->data,
     353                                                                struct ldb_dirsync_control);
     354
     355                cookie = ldb_base64_encode(mem_ctx, rep_control->cookie,
     356                                rep_control->cookie_len);
     357                if (cookie == NULL) {
     358                        return NULL;
     359                }
     360                res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%s",
     361                                        LDB_CONTROL_DIRSYNC_NAME,
     362                                        control->critical,
     363                                        rep_control->flags,
     364                                        rep_control->max_attributes,
     365                                        cookie);
     366
     367                talloc_free(cookie);
     368                return res;
     369        }
     370
     371        /*
     372         * From here we don't know the control
     373         */
     374        if (control->data == NULL) {
     375                /*
     376                 * We don't know the control but there is no real data attached to it
     377                 * so we can represent it with local_oid:oid:criticity
     378                 */
     379                res = talloc_asprintf(mem_ctx, "local_oid:%s:%d",
     380                                        control->oid,
     381                                        control->critical);
     382                return res;
     383        }
     384
     385                res = talloc_asprintf(mem_ctx, "unknown oid:%s",
     386                                        control->oid);
     387        return res;
     388}
     389
     390
     391/*
     392 * A little trick to allow to use constants defined in headers rather than
     393 * hardwritten in the file hardwritten in the file
     394 * sizeof will return the \0 char as well so it will take the place of ":" in the
     395 * length of the string
     396 */
     397#define LDB_CONTROL_CMP(control, NAME) strncmp(control, NAME ":", sizeof(NAME))
     398
     399/* Parse one string and return associated control if parsing is successful*/
     400struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings)
     401{
     402        struct ldb_control *ctrl;
    165403        char *error_string = NULL;
    166404
    167         if (control_strings == NULL || control_strings[0] == NULL)
     405        if (!(ctrl = talloc(mem_ctx, struct ldb_control))) {
     406                ldb_oom(ldb);
    168407                return NULL;
    169 
    170         for (i = 0; control_strings[i]; i++);
    171 
    172         ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
    173 
    174         for (i = 0; control_strings[i]; i++) {
    175                 if (strncmp(control_strings[i], "vlv:", 4) == 0) {
    176                         struct ldb_vlv_req_control *control;
    177                         const char *p;
    178                         char attr[1024];
    179                         char ctxid[1024];
    180                         int crit, bc, ac, os, cc, ret;
    181 
    182                         attr[0] = '\0';
    183                         ctxid[0] = '\0';
    184                         p = &(control_strings[i][4]);
    185                         ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
    186                         if (ret < 5) {
    187                                 ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
    188                         }
    189                                
    190                         if ((ret < 4) || (crit < 0) || (crit > 1)) {
    191                                 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
    192                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
    193                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, s = string, o = b64 binary blob");
     408        }
     409
     410        if (LDB_CONTROL_CMP(control_strings,
     411                                LDB_CONTROL_VLV_REQ_NAME) == 0) {
     412                struct ldb_vlv_req_control *control;
     413                const char *p;
     414                char attr[1024];
     415                char ctxid[1024];
     416                int crit, bc, ac, os, cc, ret;
     417
     418                attr[0] = '\0';
     419                ctxid[0] = '\0';
     420                p = &(control_strings[sizeof(LDB_CONTROL_VLV_REQ_NAME)]);
     421                ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
     422                if (ret < 5) {
     423                        ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
     424                }
     425                       
     426                if ((ret < 4) || (crit < 0) || (crit > 1)) {
     427                        error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
     428                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
     429                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, s = string, o = b64 binary blob");
     430                        ldb_set_errstring(ldb, error_string);
     431                        talloc_free(error_string);
     432                        return NULL;
     433                }
     434                ctrl->oid = LDB_CONTROL_VLV_REQ_OID;
     435                ctrl->critical = crit;
     436                if (!(control = talloc(ctrl,
     437                                        struct ldb_vlv_req_control))) {
     438                        ldb_oom(ldb);
     439                        return NULL;
     440                }
     441                control->beforeCount = bc;
     442                control->afterCount = ac;
     443                if (attr[0]) {
     444                        control->type = 1;
     445                        control->match.gtOrEq.value = talloc_strdup(control, attr);
     446                        control->match.gtOrEq.value_len = strlen(attr);
     447                } else {
     448                        control->type = 0;
     449                        control->match.byOffset.offset = os;
     450                        control->match.byOffset.contentCount = cc;
     451                }
     452                if (ctxid[0]) {
     453                        control->ctxid_len = ldb_base64_decode(ctxid);
     454                        control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
     455                } else {
     456                        control->ctxid_len = 0;
     457                        control->contextId = NULL;
     458                }
     459                ctrl->data = control;
     460
     461                return ctrl;
     462        }
     463
     464        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_NAME) == 0) {
     465                struct ldb_dirsync_control *control;
     466                const char *p;
     467                char cookie[1024];
     468                int crit, flags, max_attrs, ret;
     469               
     470                cookie[0] = '\0';
     471                p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_NAME)]);
     472                ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
     473
     474                if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) {
     475                        error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n");
     476                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
     477                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, o = b64 binary blob");
     478                        ldb_set_errstring(ldb, error_string);
     479                        talloc_free(error_string);
     480                        return NULL;
     481                }
     482
     483                /* w2k3 seems to ignore the parameter,
     484                        * but w2k sends a wrong cookie when this value is to small
     485                        * this would cause looping forever, while getting
     486                        * the same data and same cookie forever
     487                        */
     488                if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
     489
     490                ctrl->oid = LDB_CONTROL_DIRSYNC_OID;
     491                ctrl->critical = crit;
     492                control = talloc(ctrl, struct ldb_dirsync_control);
     493                control->flags = flags;
     494                control->max_attributes = max_attrs;
     495                if (*cookie) {
     496                        control->cookie_len = ldb_base64_decode(cookie);
     497                        control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
     498                } else {
     499                        control->cookie = NULL;
     500                        control->cookie_len = 0;
     501                }
     502                ctrl->data = control;
     503
     504                return ctrl;
     505        }
     506
     507        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_ASQ_NAME) == 0) {
     508                struct ldb_asq_control *control;
     509                const char *p;
     510                char attr[256];
     511                int crit, ret;
     512
     513                attr[0] = '\0';
     514                p = &(control_strings[sizeof(LDB_CONTROL_ASQ_NAME)]);
     515                ret = sscanf(p, "%d:%255[^$]", &crit, attr);
     516                if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
     517                        error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n");
     518                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n");
     519                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
     520                        ldb_set_errstring(ldb, error_string);
     521                        talloc_free(error_string);
     522                        return NULL;
     523                }
     524
     525                ctrl->oid = LDB_CONTROL_ASQ_OID;
     526                ctrl->critical = crit;
     527                control = talloc(ctrl, struct ldb_asq_control);
     528                control->request = 1;
     529                control->source_attribute = talloc_strdup(control, attr);
     530                control->src_attr_len = strlen(attr);
     531                ctrl->data = control;
     532
     533                return ctrl;
     534        }
     535
     536        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_EXTENDED_DN_NAME) == 0) {
     537                struct ldb_extended_dn_control *control;
     538                const char *p;
     539                int crit, type, ret;
     540
     541                p = &(control_strings[sizeof(LDB_CONTROL_EXTENDED_DN_NAME)]);
     542                ret = sscanf(p, "%d:%d", &crit, &type);
     543                if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
     544                        ret = sscanf(p, "%d", &crit);
     545                        if ((ret != 1) || (crit < 0) || (crit > 1)) {
     546                                error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
     547                                error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n");
     548                                error_string = talloc_asprintf_append(error_string, "   note: b = boolean\n");
     549                                error_string = talloc_asprintf_append(error_string, "         i = integer\n");
     550                                error_string = talloc_asprintf_append(error_string, "   valid values are: 0 - hexadecimal representation\n");
     551                                error_string = talloc_asprintf_append(error_string, "                     1 - normal string representation");
    194552                                ldb_set_errstring(ldb, error_string);
    195553                                talloc_free(error_string);
    196554                                return NULL;
    197555                        }
    198                         if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) {
    199                                 ldb_oom(ldb);
    200                                 return NULL;
     556                        control = NULL;
     557                } else {
     558                        control = talloc(ctrl, struct ldb_extended_dn_control);
     559                        control->type = type;
     560                }
     561
     562                ctrl->oid = LDB_CONTROL_EXTENDED_DN_OID;
     563                ctrl->critical = crit;
     564                ctrl->data = talloc_steal(ctrl, control);
     565
     566                return ctrl;
     567        }
     568
     569        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SD_FLAGS_NAME) == 0) {
     570                struct ldb_sd_flags_control *control;
     571                const char *p;
     572                int crit, ret;
     573                unsigned secinfo_flags;
     574
     575                p = &(control_strings[sizeof(LDB_CONTROL_SD_FLAGS_NAME)]);
     576                ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
     577                if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) {
     578                        error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n");
     579                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n");
     580                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
     581                        ldb_set_errstring(ldb, error_string);
     582                        talloc_free(error_string);
     583                        return NULL;
     584                }
     585
     586                ctrl->oid = LDB_CONTROL_SD_FLAGS_OID;
     587                ctrl->critical = crit;
     588                control = talloc(ctrl, struct ldb_sd_flags_control);
     589                control->secinfo_flags = secinfo_flags;
     590                ctrl->data = control;
     591
     592                return ctrl;
     593        }
     594
     595        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SEARCH_OPTIONS_NAME) == 0) {
     596                struct ldb_search_options_control *control;
     597                const char *p;
     598                int crit, ret;
     599                unsigned search_options;
     600
     601                p = &(control_strings[sizeof(LDB_CONTROL_SEARCH_OPTIONS_NAME)]);
     602                ret = sscanf(p, "%d:%u", &crit, &search_options);
     603                if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) {
     604                        error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n");
     605                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n");
     606                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
     607                        ldb_set_errstring(ldb, error_string);
     608                        talloc_free(error_string);
     609                        return NULL;
     610                }
     611
     612                ctrl->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
     613                ctrl->critical = crit;
     614                control = talloc(ctrl, struct ldb_search_options_control);
     615                control->search_options = search_options;
     616                ctrl->data = control;
     617
     618                return ctrl;
     619        }
     620
     621        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_BYPASS_OPERATIONAL_NAME) == 0) {
     622                const char *p;
     623                int crit, ret;
     624
     625                p = &(control_strings[sizeof(LDB_CONTROL_BYPASS_OPERATIONAL_NAME)]);
     626                ret = sscanf(p, "%d", &crit);
     627                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     628                        error_string = talloc_asprintf(mem_ctx, "invalid bypassopreational control syntax\n");
     629                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     630                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     631                        ldb_set_errstring(ldb, error_string);
     632                        talloc_free(error_string);
     633                        return NULL;
     634                }
     635
     636                ctrl->oid = LDB_CONTROL_BYPASS_OPERATIONAL_OID;
     637                ctrl->critical = crit;
     638                ctrl->data = NULL;
     639
     640                return ctrl;
     641        }
     642
     643        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RELAX_NAME) == 0) {
     644                const char *p;
     645                int crit, ret;
     646
     647                p = &(control_strings[sizeof(LDB_CONTROL_RELAX_NAME)]);
     648                ret = sscanf(p, "%d", &crit);
     649                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     650                        error_string = talloc_asprintf(mem_ctx, "invalid relax control syntax\n");
     651                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     652                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     653                        ldb_set_errstring(ldb, error_string);
     654                        talloc_free(error_string);
     655                        return NULL;
     656                }
     657
     658                ctrl->oid = LDB_CONTROL_RELAX_OID;
     659                ctrl->critical = crit;
     660                ctrl->data = NULL;
     661
     662                return ctrl;
     663        }
     664
     665        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RECALCULATE_SD_NAME) == 0) {
     666                const char *p;
     667                int crit, ret;
     668
     669                p = &(control_strings[sizeof(LDB_CONTROL_RECALCULATE_SD_NAME)]);
     670                ret = sscanf(p, "%d", &crit);
     671                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     672                        error_string = talloc_asprintf(mem_ctx, "invalid recalculate_sd control syntax\n");
     673                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     674                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     675                        ldb_set_errstring(ldb, error_string);
     676                        talloc_free(error_string);
     677                        return NULL;
     678                }
     679
     680                ctrl->oid = LDB_CONTROL_RECALCULATE_SD_OID;
     681                ctrl->critical = crit;
     682                ctrl->data = NULL;
     683
     684                return ctrl;
     685        }
     686
     687        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DOMAIN_SCOPE_NAME) == 0) {
     688                const char *p;
     689                int crit, ret;
     690
     691                p = &(control_strings[sizeof(LDB_CONTROL_DOMAIN_SCOPE_NAME)]);
     692                ret = sscanf(p, "%d", &crit);
     693                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     694                        error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
     695                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     696                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     697                        ldb_set_errstring(ldb, error_string);
     698                        talloc_free(error_string);
     699                        return NULL;
     700                }
     701
     702                ctrl->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
     703                ctrl->critical = crit;
     704                ctrl->data = NULL;
     705
     706                return ctrl;
     707        }
     708
     709        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PAGED_RESULTS_NAME) == 0) {
     710                struct ldb_paged_control *control;
     711                const char *p;
     712                int crit, size, ret;
     713               
     714                p = &(control_strings[sizeof(LDB_CONTROL_PAGED_RESULTS_NAME)]);
     715                ret = sscanf(p, "%d:%d", &crit, &size);
     716                if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
     717                        error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
     718                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
     719                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
     720                        ldb_set_errstring(ldb, error_string);
     721                        talloc_free(error_string);
     722                        return NULL;
     723                }
     724
     725                ctrl->oid = LDB_CONTROL_PAGED_RESULTS_OID;
     726                ctrl->critical = crit;
     727                control = talloc(ctrl, struct ldb_paged_control);
     728                control->size = size;
     729                control->cookie = NULL;
     730                control->cookie_len = 0;
     731                ctrl->data = control;
     732
     733                return ctrl;
     734        }
     735
     736        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SERVER_SORT_NAME) == 0) {
     737                struct ldb_server_sort_control **control;
     738                const char *p;
     739                char attr[256];
     740                char rule[128];
     741                int crit, rev, ret;
     742
     743                attr[0] = '\0';
     744                rule[0] = '\0';
     745                p = &(control_strings[sizeof(LDB_CONTROL_SERVER_SORT_NAME)]);
     746                ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
     747                if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
     748                        error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
     749                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
     750                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
     751                        ldb_set_errstring(ldb, error_string);
     752                        talloc_free(error_string);
     753                        return NULL;
     754                }
     755                ctrl->oid = LDB_CONTROL_SERVER_SORT_OID;
     756                ctrl->critical = crit;
     757                control = talloc_array(ctrl, struct ldb_server_sort_control *, 2);
     758                control[0] = talloc(control, struct ldb_server_sort_control);
     759                control[0]->attributeName = talloc_strdup(control, attr);
     760                if (rule[0])
     761                        control[0]->orderingRule = talloc_strdup(control, rule);
     762                else
     763                        control[0]->orderingRule = NULL;
     764                control[0]->reverse = rev;
     765                control[1] = NULL;
     766                ctrl->data = control;
     767
     768                return ctrl;
     769        }
     770
     771        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_NOTIFICATION_NAME) == 0) {
     772                const char *p;
     773                int crit, ret;
     774
     775                p = &(control_strings[sizeof(LDB_CONTROL_NOTIFICATION_NAME)]);
     776                ret = sscanf(p, "%d", &crit);
     777                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     778                        error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n");
     779                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     780                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     781                        ldb_set_errstring(ldb, error_string);
     782                        talloc_free(error_string);
     783                        return NULL;
     784                }
     785
     786                ctrl->oid = LDB_CONTROL_NOTIFICATION_OID;
     787                ctrl->critical = crit;
     788                ctrl->data = NULL;
     789
     790                return ctrl;
     791        }
     792
     793        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_TREE_DELETE_NAME) == 0) {
     794                const char *p;
     795                int crit, ret;
     796
     797                p = &(control_strings[sizeof(LDB_CONTROL_TREE_DELETE_NAME)]);
     798                ret = sscanf(p, "%d", &crit);
     799                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     800                        error_string = talloc_asprintf(mem_ctx, "invalid tree_delete control syntax\n");
     801                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     802                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     803                        ldb_set_errstring(ldb, error_string);
     804                        talloc_free(error_string);
     805                        return NULL;
     806                }
     807
     808                ctrl->oid = LDB_CONTROL_TREE_DELETE_OID;
     809                ctrl->critical = crit;
     810                ctrl->data = NULL;
     811
     812                return ctrl;
     813        }
     814
     815        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DELETED_NAME) == 0) {
     816                const char *p;
     817                int crit, ret;
     818
     819                p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DELETED_NAME)]);
     820                ret = sscanf(p, "%d", &crit);
     821                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     822                        error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n");
     823                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     824                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     825                        ldb_set_errstring(ldb, error_string);
     826                        talloc_free(error_string);
     827                        return NULL;
     828                }
     829
     830                ctrl->oid = LDB_CONTROL_SHOW_DELETED_OID;
     831                ctrl->critical = crit;
     832                ctrl->data = NULL;
     833
     834                return ctrl;
     835        }
     836
     837        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME) == 0) {
     838                const char *p;
     839                int crit, ret;
     840
     841                p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME)]);
     842                ret = sscanf(p, "%d", &crit);
     843                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     844                        error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link control syntax\n");
     845                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     846                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     847                        ldb_set_errstring(ldb, error_string);
     848                        talloc_free(error_string);
     849                        return NULL;
     850                }
     851
     852                ctrl->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID;
     853                ctrl->critical = crit;
     854                ctrl->data = NULL;
     855
     856                return ctrl;
     857        }
     858
     859        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_RECYCLED_NAME) == 0) {
     860                const char *p;
     861                int crit, ret;
     862
     863                p = &(control_strings[sizeof(LDB_CONTROL_SHOW_RECYCLED_NAME)]);
     864                ret = sscanf(p, "%d", &crit);
     865                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     866                        error_string = talloc_asprintf(mem_ctx, "invalid show_recycled control syntax\n");
     867                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     868                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     869                        ldb_set_errstring(ldb, error_string);
     870                        talloc_free(error_string);
     871                        return NULL;
     872                }
     873
     874                ctrl->oid = LDB_CONTROL_SHOW_RECYCLED_OID;
     875                ctrl->critical = crit;
     876                ctrl->data = NULL;
     877
     878                return ctrl;
     879        }
     880
     881        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PERMISSIVE_MODIFY_NAME) == 0) {
     882                const char *p;
     883                int crit, ret;
     884
     885                p = &(control_strings[sizeof(LDB_CONTROL_PERMISSIVE_MODIFY_NAME)]);
     886                ret = sscanf(p, "%d", &crit);
     887                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     888                        error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
     889                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     890                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     891                        ldb_set_errstring(ldb, error_string);
     892                        talloc_free(error_string);
     893                        return NULL;
     894                }
     895
     896                ctrl->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
     897                ctrl->critical = crit;
     898                ctrl->data = NULL;
     899
     900                return ctrl;
     901        }
     902
     903        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_REVEAL_INTERNALS_NAME) == 0) {
     904                const char *p;
     905                int crit, ret;
     906
     907                p = &(control_strings[sizeof(LDB_CONTROL_REVEAL_INTERNALS_NAME)]);
     908                ret = sscanf(p, "%d", &crit);
     909                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     910                        error_string = talloc_asprintf(mem_ctx, "invalid reveal_internals control syntax\n");
     911                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     912                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     913                        ldb_set_errstring(ldb, error_string);
     914                        talloc_free(error_string);
     915                        return NULL;
     916                }
     917
     918                ctrl->oid = LDB_CONTROL_REVEAL_INTERNALS;
     919                ctrl->critical = crit;
     920                ctrl->data = NULL;
     921
     922                return ctrl;
     923        }
     924
     925        if (strncmp(control_strings, "local_oid:", 10) == 0) {
     926                const char *p;
     927                int crit = 0, ret = 0;
     928                char oid[256];
     929
     930                oid[0] = '\0';
     931                p = &(control_strings[10]);
     932                ret = sscanf(p, "%64[^:]:%d", oid, &crit);
     933
     934                if ((ret != 2) || strlen(oid) == 0 || (crit < 0) || (crit > 1)) {
     935                        error_string = talloc_asprintf(mem_ctx, "invalid local_oid control syntax\n");
     936                        error_string = talloc_asprintf_append(error_string, " syntax: oid(s):crit(b)\n");
     937                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
     938                        ldb_set_errstring(ldb, error_string);
     939                        talloc_free(error_string);
     940                        return NULL;
     941                }
     942
     943                ctrl->oid = talloc_strdup(ctrl, oid);
     944                if (!ctrl->oid) {
     945                        ldb_oom(ldb);
     946                        return NULL;
     947                }
     948                ctrl->critical = crit;
     949                ctrl->data = NULL;
     950
     951                return ctrl;
     952        }
     953
     954        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RODC_DCPROMO_NAME) == 0) {
     955                const char *p;
     956                int crit, ret;
     957
     958                p = &(control_strings[sizeof(LDB_CONTROL_RODC_DCPROMO_NAME)]);
     959                ret = sscanf(p, "%d", &crit);
     960                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     961                        error_string = talloc_asprintf(mem_ctx, "invalid rodc_join control syntax\n");
     962                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     963                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     964                        ldb_set_errstring(ldb, error_string);
     965                        talloc_free(error_string);
     966                        return NULL;
     967                }
     968
     969                ctrl->oid = LDB_CONTROL_RODC_DCPROMO_OID;
     970                ctrl->critical = crit;
     971                ctrl->data = NULL;
     972
     973                return ctrl;
     974        }
     975
     976        if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PROVISION_NAME) == 0) {
     977                const char *p;
     978                int crit, ret;
     979
     980                p = &(control_strings[sizeof(LDB_CONTROL_PROVISION_NAME)]);
     981                ret = sscanf(p, "%d", &crit);
     982                if ((ret != 1) || (crit < 0) || (crit > 1)) {
     983                        error_string = talloc_asprintf(mem_ctx, "invalid provision control syntax\n");
     984                        error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
     985                        error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
     986                        ldb_set_errstring(ldb, error_string);
     987                        talloc_free(error_string);
     988                        return NULL;
     989                }
     990
     991                ctrl->oid = LDB_CONTROL_PROVISION_OID;
     992                ctrl->critical = crit;
     993                ctrl->data = NULL;
     994
     995                return ctrl;
     996        }
     997        /*
     998         * When no matching control has been found.
     999         */
     1000        return NULL;
     1001}
     1002
     1003/*
     1004 * A little trick to allow to use constants defined in headers rather than
     1005 * hardwritten in the file hardwritten in the file
     1006 * sizeof will return the \0 char as well so it will take the place of ":" in the
     1007 * length of the string
     1008 */
     1009#define LDB_CONTROL_CMP(control, NAME) strncmp(control, NAME ":", sizeof(NAME))
     1010
     1011/* Parse controls from the format used on the command line and in ejs */
     1012struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char **control_strings)
     1013{
     1014        unsigned int i;
     1015        struct ldb_control **ctrl;
     1016
     1017        if (control_strings == NULL || control_strings[0] == NULL)
     1018                return NULL;
     1019
     1020        for (i = 0; control_strings[i]; i++);
     1021
     1022        ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
     1023
     1024        ldb_reset_err_string(ldb);
     1025        for (i = 0; control_strings[i]; i++) {
     1026                ctrl[i] = ldb_parse_control_from_string(ldb, ctrl, control_strings[i]);
     1027                if (ctrl[i] == NULL) {
     1028                        if( ldb_errstring == NULL ) {
     1029                                /* no controls matched, throw an error */
     1030                                ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
    2011031                        }
    202                         ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID;
    203                         ctrl[i]->critical = crit;
    204                         if (!(control = talloc(ctrl[i],
    205                                                struct ldb_vlv_req_control))) {
    206                                 ldb_oom(ldb);
    207                                 return NULL;
    208                         }
    209                         control->beforeCount = bc;
    210                         control->afterCount = ac;
    211                         if (attr[0]) {
    212                                 control->type = 1;
    213                                 control->match.gtOrEq.value = talloc_strdup(control, attr);
    214                                 control->match.gtOrEq.value_len = strlen(attr);
    215                         } else {
    216                                 control->type = 0;
    217                                 control->match.byOffset.offset = os;
    218                                 control->match.byOffset.contentCount = cc;
    219                         }
    220                         if (ctxid[0]) {
    221                                 control->ctxid_len = ldb_base64_decode(ctxid);
    222                                 control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
    223                         } else {
    224                                 control->ctxid_len = 0;
    225                                 control->contextId = NULL;
    226                         }
    227                         ctrl[i]->data = control;
    228 
    229                         continue;
    230                 }
    231 
    232                 if (strncmp(control_strings[i], "dirsync:", 8) == 0) {
    233                         struct ldb_dirsync_control *control;
    234                         const char *p;
    235                         char cookie[1024];
    236                         int crit, flags, max_attrs, ret;
    237                        
    238                         cookie[0] = '\0';
    239                         p = &(control_strings[i][8]);
    240                         ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
    241 
    242                         if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) {
    243                                 error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n");
    244                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
    245                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, o = b64 binary blob");
    246                                 ldb_set_errstring(ldb, error_string);
    247                                 talloc_free(error_string);
    248                                 return NULL;
    249                         }
    250 
    251                         /* w2k3 seems to ignore the parameter,
    252                          * but w2k sends a wrong cookie when this value is to small
    253                          * this would cause looping forever, while getting
    254                          * the same data and same cookie forever
    255                          */
    256                         if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
    257 
    258                         ctrl[i] = talloc(ctrl, struct ldb_control);
    259                         ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID;
    260                         ctrl[i]->critical = crit;
    261                         control = talloc(ctrl[i], struct ldb_dirsync_control);
    262                         control->flags = flags;
    263                         control->max_attributes = max_attrs;
    264                         if (*cookie) {
    265                                 control->cookie_len = ldb_base64_decode(cookie);
    266                                 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
    267                         } else {
    268                                 control->cookie = NULL;
    269                                 control->cookie_len = 0;
    270                         }
    271                         ctrl[i]->data = control;
    272 
    273                         continue;
    274                 }
    275 
    276                 if (strncmp(control_strings[i], "asq:", 4) == 0) {
    277                         struct ldb_asq_control *control;
    278                         const char *p;
    279                         char attr[256];
    280                         int crit, ret;
    281 
    282                         attr[0] = '\0';
    283                         p = &(control_strings[i][4]);
    284                         ret = sscanf(p, "%d:%255[^$]", &crit, attr);
    285                         if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
    286                                 error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n");
    287                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n");
    288                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
    289                                 ldb_set_errstring(ldb, error_string);
    290                                 talloc_free(error_string);
    291                                 return NULL;
    292                         }
    293 
    294                         ctrl[i] = talloc(ctrl, struct ldb_control);
    295                         if (!ctrl[i]) {
    296                                 ldb_oom(ldb);
    297                                 return NULL;
    298                         }
    299                         ctrl[i]->oid = LDB_CONTROL_ASQ_OID;
    300                         ctrl[i]->critical = crit;
    301                         control = talloc(ctrl[i], struct ldb_asq_control);
    302                         control->request = 1;
    303                         control->source_attribute = talloc_strdup(control, attr);
    304                         control->src_attr_len = strlen(attr);
    305                         ctrl[i]->data = control;
    306 
    307                         continue;
    308                 }
    309 
    310                 if (strncmp(control_strings[i], "extended_dn:", 12) == 0) {
    311                         struct ldb_extended_dn_control *control;
    312                         const char *p;
    313                         int crit, type, ret;
    314 
    315                         p = &(control_strings[i][12]);
    316                         ret = sscanf(p, "%d:%d", &crit, &type);
    317                         if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
    318                                 ret = sscanf(p, "%d", &crit);
    319                                 if ((ret != 1) || (crit < 0) || (crit > 1)) {
    320                                         error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
    321                                         error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n");
    322                                         error_string = talloc_asprintf_append(error_string, "   note: b = boolean\n");
    323                                         error_string = talloc_asprintf_append(error_string, "         i = integer\n");
    324                                         error_string = talloc_asprintf_append(error_string, "   valid values are: 0 - hexadecimal representation\n");
    325                                         error_string = talloc_asprintf_append(error_string, "                     1 - normal string representation");
    326                                         ldb_set_errstring(ldb, error_string);
    327                                         talloc_free(error_string);
    328                                         return NULL;
    329                                 }
    330                                 control = NULL;
    331                         } else {
    332                                 control = talloc(ctrl, struct ldb_extended_dn_control);
    333                                 control->type = type;
    334                         }
    335 
    336                         ctrl[i] = talloc(ctrl, struct ldb_control);
    337                         if (!ctrl[i]) {
    338                                 ldb_oom(ldb);
    339                                 return NULL;
    340                         }
    341                         ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
    342                         ctrl[i]->critical = crit;
    343                         ctrl[i]->data = talloc_steal(ctrl[i], control);
    344 
    345                         continue;
    346                 }
    347 
    348                 if (strncmp(control_strings[i], "sd_flags:", 9) == 0) {
    349                         struct ldb_sd_flags_control *control;
    350                         const char *p;
    351                         int crit, ret;
    352                         unsigned secinfo_flags;
    353 
    354                         p = &(control_strings[i][9]);
    355                         ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
    356                         if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) {
    357                                 error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n");
    358                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n");
    359                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
    360                                 ldb_set_errstring(ldb, error_string);
    361                                 talloc_free(error_string);
    362                                 return NULL;
    363                         }
    364 
    365                         ctrl[i] = talloc(ctrl, struct ldb_control);
    366                         if (!ctrl[i]) {
    367                                 ldb_oom(ldb);
    368                                 return NULL;
    369                         }
    370                         ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID;
    371                         ctrl[i]->critical = crit;
    372                         control = talloc(ctrl[i], struct ldb_sd_flags_control);
    373                         control->secinfo_flags = secinfo_flags;
    374                         ctrl[i]->data = control;
    375 
    376                         continue;
    377                 }
    378 
    379                 if (strncmp(control_strings[i], "search_options:", 15) == 0) {
    380                         struct ldb_search_options_control *control;
    381                         const char *p;
    382                         int crit, ret;
    383                         unsigned search_options;
    384 
    385                         p = &(control_strings[i][15]);
    386                         ret = sscanf(p, "%d:%u", &crit, &search_options);
    387                         if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) {
    388                                 error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n");
    389                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n");
    390                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
    391                                 ldb_set_errstring(ldb, error_string);
    392                                 talloc_free(error_string);
    393                                 return NULL;
    394                         }
    395 
    396                         ctrl[i] = talloc(ctrl, struct ldb_control);
    397                         if (!ctrl[i]) {
    398                                 ldb_oom(ldb);
    399                                 return NULL;
    400                         }
    401                         ctrl[i]->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
    402                         ctrl[i]->critical = crit;
    403                         control = talloc(ctrl[i], struct ldb_search_options_control);
    404                         control->search_options = search_options;
    405                         ctrl[i]->data = control;
    406 
    407                         continue;
    408                 }
    409 
    410                 if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
    411                         const char *p;
    412                         int crit, ret;
    413 
    414                         p = &(control_strings[i][13]);
    415                         ret = sscanf(p, "%d", &crit);
    416                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
    417                                 error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
    418                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
    419                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
    420                                 ldb_set_errstring(ldb, error_string);
    421                                 talloc_free(error_string);
    422                                 return NULL;
    423                         }
    424 
    425                         ctrl[i] = talloc(ctrl, struct ldb_control);
    426                         if (!ctrl[i]) {
    427                                 ldb_oom(ldb);
    428                                 return NULL;
    429                         }
    430                         ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
    431                         ctrl[i]->critical = crit;
    432                         ctrl[i]->data = NULL;
    433 
    434                         continue;
    435                 }
    436 
    437                 if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
    438                         struct ldb_paged_control *control;
    439                         const char *p;
    440                         int crit, size, ret;
    441                        
    442                         p = &(control_strings[i][14]);
    443                         ret = sscanf(p, "%d:%d", &crit, &size);
    444 
    445                         if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
    446                                 error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
    447                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
    448                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
    449                                 ldb_set_errstring(ldb, error_string);
    450                                 talloc_free(error_string);
    451                                 return NULL;
    452                         }
    453 
    454                         ctrl[i] = talloc(ctrl, struct ldb_control);
    455                         if (!ctrl[i]) {
    456                                 ldb_oom(ldb);
    457                                 return NULL;
    458                         }
    459                         ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
    460                         ctrl[i]->critical = crit;
    461                         control = talloc(ctrl[i], struct ldb_paged_control);
    462                         control->size = size;
    463                         control->cookie = NULL;
    464                         control->cookie_len = 0;
    465                         ctrl[i]->data = control;
    466 
    467                         continue;
    468                 }
    469 
    470                 if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
    471                         struct ldb_server_sort_control **control;
    472                         const char *p;
    473                         char attr[256];
    474                         char rule[128];
    475                         int crit, rev, ret;
    476 
    477                         attr[0] = '\0';
    478                         rule[0] = '\0';
    479                         p = &(control_strings[i][12]);
    480                         ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
    481                         if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
    482                                 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
    483                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
    484                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
    485                                 ldb_set_errstring(ldb, error_string);
    486                                 talloc_free(error_string);
    487                                 return NULL;
    488                         }
    489                         ctrl[i] = talloc(ctrl, struct ldb_control);
    490                         if (!ctrl[i]) {
    491                                 ldb_oom(ldb);
    492                                 return NULL;
    493                         }
    494                         ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID;
    495                         ctrl[i]->critical = crit;
    496                         control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
    497                         control[0] = talloc(control, struct ldb_server_sort_control);
    498                         control[0]->attributeName = talloc_strdup(control, attr);
    499                         if (rule[0])
    500                                 control[0]->orderingRule = talloc_strdup(control, rule);
    501                         else
    502                                 control[0]->orderingRule = NULL;
    503                         control[0]->reverse = rev;
    504                         control[1] = NULL;
    505                         ctrl[i]->data = control;
    506 
    507                         continue;
    508                 }
    509 
    510                 if (strncmp(control_strings[i], "notification:", 13) == 0) {
    511                         const char *p;
    512                         int crit, ret;
    513 
    514                         p = &(control_strings[i][13]);
    515                         ret = sscanf(p, "%d", &crit);
    516                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
    517                                 error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n");
    518                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
    519                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
    520                                 ldb_set_errstring(ldb, error_string);
    521                                 talloc_free(error_string);
    522                                 return NULL;
    523                         }
    524 
    525                         ctrl[i] = talloc(ctrl, struct ldb_control);
    526                         if (!ctrl[i]) {
    527                                 ldb_oom(ldb);
    528                                 return NULL;
    529                         }
    530                         ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID;
    531                         ctrl[i]->critical = crit;
    532                         ctrl[i]->data = NULL;
    533 
    534                         continue;
    535                 }
    536 
    537                 if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
    538                         const char *p;
    539                         int crit, ret;
    540 
    541                         p = &(control_strings[i][13]);
    542                         ret = sscanf(p, "%d", &crit);
    543                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
    544                                 error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n");
    545                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
    546                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
    547                                 ldb_set_errstring(ldb, error_string);
    548                                 talloc_free(error_string);
    549                                 return NULL;
    550                         }
    551 
    552                         ctrl[i] = talloc(ctrl, struct ldb_control);
    553                         if (!ctrl[i]) {
    554                                 ldb_oom(ldb);
    555                                 return NULL;
    556                         }
    557                         ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID;
    558                         ctrl[i]->critical = crit;
    559                         ctrl[i]->data = NULL;
    560 
    561                         continue;
    562                 }
    563 
    564                 if (strncmp(control_strings[i], "show_deactivated_link:", 22) == 0) {
    565                         const char *p;
    566                         int crit, ret;
    567 
    568                         p = &(control_strings[i][22]);
    569                         ret = sscanf(p, "%d", &crit);
    570                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
    571                                 error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link control syntax\n");
    572                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
    573                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
    574                                 ldb_set_errstring(ldb, error_string);
    575                                 talloc_free(error_string);
    576                                 return NULL;
    577                         }
    578 
    579                         ctrl[i] = talloc(ctrl, struct ldb_control);
    580                         if (!ctrl[i]) {
    581                                 ldb_oom(ldb);
    582                                 return NULL;
    583                         }
    584                         ctrl[i]->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID;
    585                         ctrl[i]->critical = crit;
    586                         ctrl[i]->data = NULL;
    587 
    588                         continue;
    589                 }
    590 
    591                 if (strncmp(control_strings[i], "show_recycled:", 14) == 0) {
    592                         const char *p;
    593                         int crit, ret;
    594 
    595                         p = &(control_strings[i][14]);
    596                         ret = sscanf(p, "%d", &crit);
    597                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
    598                                 error_string = talloc_asprintf(mem_ctx, "invalid show_recycled control syntax\n");
    599                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
    600                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
    601                                 ldb_set_errstring(ldb, error_string);
    602                                 talloc_free(error_string);
    603                                 return NULL;
    604                         }
    605 
    606                         ctrl[i] = talloc(ctrl, struct ldb_control);
    607                         if (!ctrl[i]) {
    608                                 ldb_oom(ldb);
    609                                 return NULL;
    610                         }
    611                         ctrl[i]->oid = LDB_CONTROL_SHOW_RECYCLED_OID;
    612                         ctrl[i]->critical = crit;
    613                         ctrl[i]->data = NULL;
    614 
    615                         continue;
    616                 }
    617 
    618                 if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
    619                         const char *p;
    620                         int crit, ret;
    621 
    622                         p = &(control_strings[i][18]);
    623                         ret = sscanf(p, "%d", &crit);
    624                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
    625                                 error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
    626                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
    627                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
    628                                 ldb_set_errstring(ldb, error_string);
    629                                 talloc_free(error_string);
    630                                 return NULL;
    631                         }
    632 
    633                         ctrl[i] = talloc(ctrl, struct ldb_control);
    634                         if (!ctrl[i]) {
    635                                 ldb_oom(ldb);
    636                                 return NULL;
    637                         }
    638                         ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
    639                         ctrl[i]->critical = crit;
    640                         ctrl[i]->data = NULL;
    641 
    642                         continue;
    643                 }
    644 
    645                 /* no controls matched, throw an error */
    646                 ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
    647                 return NULL;
     1032                        talloc_free(ctrl);
     1033                        return NULL;
     1034                }
    6481035        }
    6491036
  • trunk/server/source4/lib/ldb/common/ldb_dn.c

    r414 r745  
    8080};
    8181
     82/* it is helpful to be able to break on this in gdb */
     83static void ldb_dn_mark_invalid(struct ldb_dn *dn)
     84{
     85        dn->invalid = true;
     86}
     87
    8288/* strdn may be NULL */
    83 struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx,
     89struct ldb_dn *ldb_dn_from_ldb_val(TALLOC_CTX *mem_ctx,
    8490                                   struct ldb_context *ldb,
    8591                                   const struct ldb_val *strdn)
     
    9096
    9197        if (strdn && strdn->data
    92             && (strlen((const char*)strdn->data) != strdn->length)) {
     98            && (strnlen((const char*)strdn->data, strdn->length) != strdn->length)) {
    9399                /* The RDN must not contain a character with value 0x0 */
    94100                return NULL;
     
    98104        LDB_DN_NULL_FAILED(dn);
    99105
    100         dn->ldb = ldb;
     106        dn->ldb = talloc_get_type(ldb, struct ldb_context);
     107        if (dn->ldb == NULL) {
     108                /* the caller probably got the arguments to
     109                   ldb_dn_new() mixed up */
     110                talloc_free(dn);
     111                return NULL;
     112        }
    101113
    102114        if (strdn->data && strdn->length) {
     
    143155
    144156/* strdn may be NULL */
    145 struct ldb_dn *ldb_dn_new(void *mem_ctx,
     157struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx,
    146158                          struct ldb_context *ldb,
    147159                          const char *strdn)
    148160{
    149161        struct ldb_val blob;
    150         blob.data = strdn;
     162        blob.data = discard_const_p(uint8_t, strdn);
    151163        blob.length = strdn ? strlen(strdn) : 0;
    152164        return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
    153165}
    154166
    155 struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx,
     167struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx,
    156168                              struct ldb_context *ldb,
    157169                              const char *new_fmt, ...)
     
    175187}
    176188
     189/* see RFC2253 section 2.4 */
    177190static int ldb_dn_escape_internal(char *dst, const char *src, int len)
    178191{
    179192        const char *p, *s;
    180193        char *d;
    181         int l;
     194        size_t l;
    182195
    183196        p = s = src;
     
    185198
    186199        while (p - src < len) {
    187 
    188                 p += strcspn(p, ",=\n+<>#;\\\"");
     200                p += strcspn(p, ",=\n\r+<>#;\\\" ");
    189201
    190202                if (p - src == len) /* found no escapable chars */
     
    194206                memcpy(d, s, p - s);
    195207                d += (p - s); /* move to current position */
    196 
    197                 if (*p) { /* it is a normal escapable character */
     208               
     209                switch (*p) {
     210                case ' ':
     211                        if (p == src || (p-src)==(len-1)) {
     212                                /* if at the beginning or end
     213                                 * of the string then escape */
     214                                *d++ = '\\';
     215                                *d++ = *p++;                                     
     216                        } else {
     217                                /* otherwise don't escape */
     218                                *d++ = *p++;
     219                        }
     220                        break;
     221
     222                case '#':
     223                        /* despite the RFC, windows escapes a #
     224                           anywhere in the string */
     225                case ',':
     226                case '+':
     227                case '"':
     228                case '\\':
     229                case '<':
     230                case '>':
     231                case '?':
     232                        /* these must be escaped using \c form */
    198233                        *d++ = '\\';
    199234                        *d++ = *p++;
    200                 } else { /* we have a zero byte in the string */
    201                         strncpy(d, "\00", 3); /* escape the zero */
    202                         d += 3;
    203                         p++; /* skip the zero */
     235                        break;
     236
     237                default: {
     238                        /* any others get \XX form */
     239                        unsigned char v;
     240                        const char *hexbytes = "0123456789ABCDEF";
     241                        v = *(const unsigned char *)p;
     242                        *d++ = '\\';
     243                        *d++ = hexbytes[v>>4];
     244                        *d++ = hexbytes[v&0xF];
     245                        p++;
     246                        break;
     247                }
    204248                }
    205249                s = p; /* move forward */
     
    214258}
    215259
    216 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
     260char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value)
    217261{
    218262        char *dst;
     
    245289{
    246290        char *p, *ex_name, *ex_value, *data, *d, *dt, *t;
    247         bool trim = false;
    248         bool in_extended = false;
     291        bool trim = true;
     292        bool in_extended = true;
    249293        bool in_ex_name = false;
    250294        bool in_ex_value = false;
     
    254298        bool is_oid = false;
    255299        bool escape = false;
    256         unsigned x;
    257         int l, ret;
     300        unsigned int x;
     301        size_t l;
     302        int ret;
    258303        char *parse_dn;
     304        bool is_index;
    259305
    260306        if ( ! dn || dn->invalid) return false;
     
    274320        }
    275321
    276         /* The RDN size must be less than 255 characters */
    277         if (strlen(parse_dn) > 255) {
    278                 return false;
    279         }
     322        is_index = (strncmp(parse_dn, "DN=@INDEX:", 10) == 0);
    280323
    281324        /* Empty DNs */
     
    289332        }
    290333
    291         /* make sure we free this if alloced previously before replacing */
    292         talloc_free(dn->components);
    293 
    294         talloc_free(dn->ext_components);
    295         dn->ext_components = NULL;
     334        /* make sure we free this if allocated previously before replacing */
     335        LDB_FREE(dn->components);
     336        dn->comp_num = 0;
     337
     338        LDB_FREE(dn->ext_components);
     339        dn->ext_comp_num = 0;
    296340
    297341        /* in the common case we have 3 or more components */
     
    301345                return false;
    302346        }
    303         dn->comp_num = 0;
    304347
    305348        /* Components data space is allocated here once */
     
    310353
    311354        p = parse_dn;
    312         in_extended = true;
    313         in_ex_name = false;
    314         in_ex_value = false;
    315         trim = true;
    316355        t = NULL;
    317356        d = dt = data;
     
    384423                                                          &ex_val, &dn->ext_components[dn->ext_comp_num].value);
    385424                                if (ret != LDB_SUCCESS) {
    386                                         dn->invalid = true;
     425                                        ldb_dn_mark_invalid(dn);
    387426                                        goto failed;
    388427                                }
     
    399438                                        continue;
    400439                                } else {
    401                                         dn->invalid = true;
     440                                        ldb_dn_mark_invalid(dn);
    402441                                        goto failed;
    403442                                }
     
    419458                                if (!isascii(*p)) {
    420459                                        /* attr names must be ascii only */
    421                                         dn->invalid = true;
     460                                        ldb_dn_mark_invalid(dn);
    422461                                        goto failed;
    423462                                }
     
    429468                                        /* not a digit nor an alpha,
    430469                                         * invalid attribute name */
    431                                         dn->invalid = true;
     470                                        ldb_dn_mark_invalid(dn);
    432471                                        goto failed;
    433472                                }
     
    448487                        if (trim && (*p != '=')) {
    449488                                /* spaces/tabs are not allowed */
    450                                 dn->invalid = true;
     489                                ldb_dn_mark_invalid(dn);
    451490                                goto failed;
    452491                        }
     
    477516                        if (!isascii(*p)) {
    478517                                /* attr names must be ascii only */
    479                                 dn->invalid = true;
     518                                ldb_dn_mark_invalid(dn);
    480519                                goto failed;
    481520                        }
     
    484523                                /* not a digit nor a dot,
    485524                                 * invalid attribute oid */
    486                                 dn->invalid = true;
     525                                ldb_dn_mark_invalid(dn);
    487526                                goto failed;
    488527                        } else
    489528                        if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {
    490529                                /* not ALPHA, DIGIT or HYPHEN */
    491                                 dn->invalid = true;
     530                                ldb_dn_mark_invalid(dn);
    492531                                goto failed;
    493532                        }
     
    579618                                continue;
    580619
     620                        case '+':
    581621                        case '=':
    582                         case '\n':
    583                         case '+':
     622                                /* to main compatibility with earlier
     623                                versions of ldb indexing, we have to
     624                                accept the base64 encoded binary index
     625                                values, which contain a '+' or '='
     626                                which should normally be escaped */
     627                                if (is_index) {
     628                                        if ( t ) t = NULL;
     629                                        *d++ = *p++;
     630                                        l++;
     631                                        break;
     632                                }
     633                                /* fall through */
     634                        case '\"':
    584635                        case '<':
    585636                        case '>':
    586                         case '#':
    587637                        case ';':
    588                         case '\"':
    589638                                /* a string with not escaped specials is invalid (tested) */
    590639                                if ( ! escape) {
    591                                         dn->invalid = true;
     640                                        ldb_dn_mark_invalid(dn);
    592641                                        goto failed;
    593642                                }
     
    616665                        default:
    617666                                if (escape) {
    618                                         if (sscanf(p, "%02x", &x) != 1) {
    619                                                 /* invalid escaping sequence */
    620                                                 dn->invalid = true;
    621                                                 goto failed;
     667                                        if (isxdigit(p[0]) && isxdigit(p[1])) {
     668                                                if (sscanf(p, "%02x", &x) != 1) {
     669                                                        /* invalid escaping sequence */
     670                                                        ldb_dn_mark_invalid(dn);
     671                                                        goto failed;
     672                                                }
     673                                                p += 2;
     674                                                *d++ = (unsigned char)x;
     675                                        } else {
     676                                                *d++ = *p++;
    622677                                        }
     678
    623679                                        escape = false;
    624 
    625                                         p += 2;
    626                                         *d++ = (unsigned char)x;
    627680                                        l++;
    628 
    629681                                        if ( t ) t = NULL;
    630682                                        break;
     
    648700        if (in_attr || in_quote) {
    649701                /* invalid dn */
    650                 dn->invalid = true;
     702                ldb_dn_mark_invalid(dn);
    651703                goto failed;
    652704        }
     
    674726
    675727failed:
     728        LDB_FREE(dn->components); /* "data" is implicitly free'd */
    676729        dn->comp_num = 0;
    677         talloc_free(dn->components);
     730        LDB_FREE(dn->ext_components);
     731        dn->ext_comp_num = 0;
     732
    678733        return false;
    679734}
     
    686741const char *ldb_dn_get_linearized(struct ldb_dn *dn)
    687742{
    688         int i, len;
     743        unsigned int i;
     744        size_t len;
    689745        char *d, *n;
    690746
     
    694750
    695751        if ( ! dn->components) {
    696                 dn->invalid = true;
     752                ldb_dn_mark_invalid(dn);
    697753                return NULL;
    698754        }
     
    741797}
    742798
    743 char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
     799static int ldb_dn_extended_component_compare(const void *p1, const void *p2)
     800{
     801        const struct ldb_dn_ext_component *ec1 = (const struct ldb_dn_ext_component *)p1;
     802        const struct ldb_dn_ext_component *ec2 = (const struct ldb_dn_ext_component *)p2;
     803        return strcmp(ec1->name, ec2->name);
     804}
     805
     806char *ldb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int mode)
    744807{
    745808        const char *linearized = ldb_dn_get_linearized(dn);
    746         char *p;
    747         int i;
     809        char *p = NULL;
     810        unsigned int i;
    748811
    749812        if (!linearized) {
     
    758821                return NULL;
    759822        }
     823
     824        /* sort the extended components by name. The idea is to make
     825         * the resulting DNs consistent, plus to ensure that we put
     826         * 'DELETED' first, so it can be very quickly recognised
     827         */
     828        TYPESAFE_QSORT(dn->ext_components, dn->ext_comp_num,
     829                       ldb_dn_extended_component_compare);
    760830
    761831        for (i = 0; i < dn->ext_comp_num; i++) {
     
    767837
    768838                ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
     839                if (!ext_syntax) {
     840                        return NULL;
     841                }
    769842
    770843                if (mode == 1) {
     
    783856
    784857                if (i == 0) {
    785                         p = talloc_asprintf(mem_ctx, "<%s=%s>",
    786                                                         name, val.data);
     858                        p = talloc_asprintf(mem_ctx, "<%s=%s>", 
     859                                            name, val.data);
    787860                } else {
    788                         p = talloc_asprintf_append(p, ";<%s=%s>",
    789                                                         name, val.data);
     861                        p = talloc_asprintf_append_buffer(p, ";<%s=%s>",
     862                                                          name, val.data);
    790863                }
    791864
     
    798871
    799872        if (dn->ext_comp_num && *linearized) {
    800                 p = talloc_asprintf_append(p, ";%s", linearized);
     873                p = talloc_asprintf_append_buffer(p, ";%s", linearized);
    801874        }
    802875
     
    808881}
    809882
    810 
    811 
    812 char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
     883/*
     884  filter out all but an acceptable list of extended DN components
     885 */
     886void ldb_dn_extended_filter(struct ldb_dn *dn, const char * const *accept_list)
     887{
     888        unsigned int i;
     889        for (i=0; i<dn->ext_comp_num; i++) {
     890                if (!ldb_attr_in_list(accept_list, dn->ext_components[i].name)) {
     891                        memmove(&dn->ext_components[i],
     892                                &dn->ext_components[i+1],
     893                                (dn->ext_comp_num-(i+1))*sizeof(dn->ext_components[0]));
     894                        dn->ext_comp_num--;
     895                        i--;
     896                }
     897        }
     898        LDB_FREE(dn->ext_linearized);
     899}
     900
     901
     902char *ldb_dn_alloc_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
    813903{
    814904        return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
     
    822912static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
    823913{
    824         int i, ret;
     914        unsigned int i;
     915        int ret;
    825916
    826917        if ( ! dn || dn->invalid) return false;
     
    867958const char *ldb_dn_get_casefold(struct ldb_dn *dn)
    868959{
    869         int i, len;
     960        unsigned int i;
     961        size_t len;
    870962        char *d, *n;
    871963
     
    9241016}
    9251017
    926 char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn)
     1018char *ldb_dn_alloc_casefold(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
    9271019{
    9281020        return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn));
     
    9371029{
    9381030        int ret;
    939         int n_base, n_dn;
     1031        unsigned int n_base, n_dn;
    9401032
    9411033        if ( ! base || base->invalid) return 1;
     
    9731065        }
    9741066
    975         if (dn->comp_num == 0) {
     1067        if ((dn->comp_num == 0) || (base->comp_num == 0)) {
    9761068                if (dn->special && base->special) {
    9771069                        return strcmp(base->linearized, dn->linearized);
     
    9881080        n_dn = dn->comp_num - 1;
    9891081
    990         while (n_base >= 0) {
     1082        while (n_base != (unsigned int) -1) {
    9911083                char *b_name = base->components[n_base].cf_name;
    9921084                char *dn_name = dn->components[n_dn].cf_name;
     
    10231115int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
    10241116{
    1025         int i, ret;
     1117        unsigned int i;
     1118        int ret;
    10261119
    10271120        if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) {
     
    10941187
    10951188static struct ldb_dn_component ldb_dn_copy_component(
    1096                                                 void *mem_ctx,
     1189                                                TALLOC_CTX *mem_ctx,
    10971190                                                struct ldb_dn_component *src)
    10981191{
     
    11401233
    11411234static struct ldb_dn_ext_component ldb_dn_ext_copy_component(
    1142                                                 void *mem_ctx,
     1235                                                TALLOC_CTX *mem_ctx,
    11431236                                                struct ldb_dn_ext_component *src)
    11441237{
     
    11651258}
    11661259
    1167 struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
     1260struct ldb_dn *ldb_dn_copy(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
    11681261{
    11691262        struct ldb_dn *new_dn;
     
    11811274
    11821275        if (dn->components) {
    1183                 int i;
     1276                unsigned int i;
    11841277
    11851278                new_dn->components =
     
    12041297
    12051298        if (dn->ext_components) {
    1206                 int i;
     1299                unsigned int i;
    12071300
    12081301                new_dn->ext_components =
     
    12701363
    12711364        if (dn->components) {
    1272                 int i;
     1365                unsigned int i;
    12731366
    12741367                if ( ! ldb_dn_validate(base)) {
     
    12881381                                                dn->comp_num + base->comp_num);
    12891382                if ( ! dn->components) {
    1290                         dn->invalid = true;
     1383                        ldb_dn_mark_invalid(dn);
    12911384                        return false;
    12921385                }
     
    12971390                                                        &base->components[i]);
    12981391                        if (dn->components[dn->comp_num].value.data == NULL) {
    1299                                 dn->invalid = true;
     1392                                ldb_dn_mark_invalid(dn);
    13001393                                return false;
    13011394                        }
     
    13281421                }
    13291422                if ( ! t) {
    1330                         dn->invalid = true;
     1423                        ldb_dn_mark_invalid(dn);
    13311424                        return false;
    13321425                }
     
    13371430        /* Wipe the ext_linearized DN,
    13381431         * the GUID and SID are almost certainly no longer valid */
    1339         if (dn->ext_linearized) {
    1340                 LDB_FREE(dn->ext_linearized);
    1341         }
    1342 
     1432        LDB_FREE(dn->ext_linearized);
    13431433        LDB_FREE(dn->ext_components);
    13441434        dn->ext_comp_num = 0;
     1435
    13451436        return true;
    13461437}
     
    13941485
    13951486        if (dn->components) {
    1396                 int n, i, j;
     1487                unsigned int n;
     1488                unsigned int i, j;
     1489
     1490                if (dn->comp_num == 0) {
     1491                        return false;
     1492                }
    13971493
    13981494                if ( ! ldb_dn_validate(child)) {
     
    14141510                                                n);
    14151511                if ( ! dn->components) {
    1416                         dn->invalid = true;
     1512                        ldb_dn_mark_invalid(dn);
    14171513                        return false;
    14181514                }
    14191515
    1420                 for (i = dn->comp_num - 1, j = n - 1; i >= 0; i--, j--) {
     1516                for (i = dn->comp_num - 1, j = n - 1; i != (unsigned int) -1;
     1517                     i--, j--) {
    14211518                        dn->components[j] = dn->components[i];
    14221519                }
     
    14271524                                                        &child->components[i]);
    14281525                        if (dn->components[i].value.data == NULL) {
    1429                                 dn->invalid = true;
     1526                                ldb_dn_mark_invalid(dn);
    14301527                                return false;
    14311528                        }
     
    14421539
    14431540        if (dn->linearized) {
     1541                if (dn->linearized[0] == '\0') {
     1542                        return false;
     1543                }
    14441544
    14451545                s = ldb_dn_get_linearized(child);
     
    14501550                t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
    14511551                if ( ! t) {
    1452                         dn->invalid = true;
     1552                        ldb_dn_mark_invalid(dn);
    14531553                        return false;
    14541554                }
     
    14601560         * the GUID and SID are almost certainly no longer valid */
    14611561        LDB_FREE(dn->ext_linearized);
    1462 
    14631562        LDB_FREE(dn->ext_components);
    14641563        dn->ext_comp_num = 0;
     
    15021601bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
    15031602{
    1504         int i;
     1603        unsigned int i;
    15051604
    15061605        if ( ! ldb_dn_validate(dn)) {
     
    15131612
    15141613        /* free components */
    1515         for (i = num; i > 0; i--) {
    1516                 LDB_FREE(dn->components[dn->comp_num - i].name);
    1517                 LDB_FREE(dn->components[dn->comp_num - i].value.data);
    1518                 LDB_FREE(dn->components[dn->comp_num - i].cf_name);
    1519                 LDB_FREE(dn->components[dn->comp_num - i].cf_value.data);
     1614        for (i = dn->comp_num - num; i < dn->comp_num; i++) {
     1615                LDB_FREE(dn->components[i].name);
     1616                LDB_FREE(dn->components[i].value.data);
     1617                LDB_FREE(dn->components[i].cf_name);
     1618                LDB_FREE(dn->components[i].cf_value.data);
    15201619        }
    15211620
     
    15361635         * the GUID and SID are almost certainly no longer valid */
    15371636        LDB_FREE(dn->ext_linearized);
    1538 
    15391637        LDB_FREE(dn->ext_components);
    15401638        dn->ext_comp_num = 0;
     
    15451643bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
    15461644{
    1547         int i, j;
     1645        unsigned int i, j;
    15481646
    15491647        if ( ! ldb_dn_validate(dn)) {
     
    15811679         * the GUID and SID are almost certainly no longer valid */
    15821680        LDB_FREE(dn->ext_linearized);
    1583 
    15841681        LDB_FREE(dn->ext_components);
    15851682        dn->ext_comp_num = 0;
     1683
    15861684        return true;
    15871685}
    15881686
    1589 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
     1687struct ldb_dn *ldb_dn_get_parent(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
    15901688{
    15911689        struct ldb_dn *new_dn;
     
    16011699        }
    16021700
    1603         /* Wipe the ext_linearized DN,
    1604          * the GUID and SID are almost certainly no longer valid */
    1605         LDB_FREE(dn->ext_linearized);
    1606 
    1607         LDB_FREE(dn->ext_components);
    1608         dn->ext_comp_num = 0;
    16091701        return new_dn;
    16101702}
     
    16191711
    16201712*/
    1621 static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
    1622         int i;
     1713static char *ldb_dn_canonical(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int ex_format) {
     1714        unsigned int i;
    16231715        TALLOC_CTX *tmpctx;
    16241716        char *cracked = NULL;
     
    16321724
    16331725        /* Walk backwards down the DN, grabbing 'dc' components at first */
    1634         for (i = dn->comp_num - 1 ; i >= 0; i--) {
     1726        for (i = dn->comp_num - 1; i != (unsigned int) -1; i--) {
    16351727                if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
    16361728                        break;
     
    16511743
    16521744        /* Only domain components?  Finish here */
    1653         if (i < 0) {
     1745        if (i == (unsigned int) -1) {
    16541746                cracked = talloc_strdup_append_buffer(cracked, format);
    16551747                talloc_steal(mem_ctx, cracked);
     
    16791771
    16801772/* Wrapper functions for the above, for the two different string formats */
    1681 char *ldb_dn_canonical_string(void *mem_ctx, struct ldb_dn *dn) {
     1773char *ldb_dn_canonical_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) {
    16821774        return ldb_dn_canonical(mem_ctx, dn, 0);
    16831775
    16841776}
    16851777
    1686 char *ldb_dn_canonical_ex_string(void *mem_ctx, struct ldb_dn *dn) {
     1778char *ldb_dn_canonical_ex_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) {
    16871779        return ldb_dn_canonical(mem_ctx, dn, 1);
    16881780}
     
    16941786        }
    16951787        return dn->comp_num;
     1788}
     1789
     1790int ldb_dn_get_extended_comp_num(struct ldb_dn *dn)
     1791{
     1792        if ( ! ldb_dn_validate(dn)) {
     1793                return -1;
     1794        }
     1795        return dn->ext_comp_num;
    16961796}
    16971797
     
    17651865
    17661866        if (dn->valid_case) {
    1767                 int i;
     1867                unsigned int i;
    17681868                for (i = 0; i < dn->comp_num; i++) {
    17691869                        LDB_FREE(dn->components[i].cf_name);
     
    17781878         * the GUID and SID are almost certainly no longer valid */
    17791879        LDB_FREE(dn->ext_linearized);
    1780 
     1880        LDB_FREE(dn->ext_components);
    17811881        dn->ext_comp_num = 0;
    1782         LDB_FREE(dn->ext_components);
     1882
    17831883        return LDB_SUCCESS;
    17841884}
     
    17871887                                                    const char *name)
    17881888{
    1789         int i;
     1889        unsigned int i;
    17901890        if ( ! ldb_dn_validate(dn)) {
    17911891                return NULL;
     
    18031903{
    18041904        struct ldb_dn_ext_component *p;
    1805         int i;
     1905        unsigned int i;
     1906        struct ldb_val v2;
    18061907
    18071908        if ( ! ldb_dn_validate(dn)) {
    18081909                return LDB_ERR_OTHER;
     1910        }
     1911
     1912        if (!ldb_dn_extended_syntax_by_name(dn->ldb, name)) {
     1913                /* We don't know how to handle this type of thing */
     1914                return LDB_ERR_INVALID_DN_SYNTAX;
    18091915        }
    18101916
     
    18191925                                if (!dn->ext_components[i].name ||
    18201926                                    !dn->ext_components[i].value.data) {
    1821                                         dn->invalid = true;
     1927                                        ldb_dn_mark_invalid(dn);
    18221928                                        return LDB_ERR_OPERATIONS_ERROR;
    18231929                                }
    1824 
    18251930                        } else {
    18261931                                if (i != (dn->ext_comp_num - 1)) {
     
    18371942                                                   dn->ext_comp_num);
    18381943                                if (!dn->ext_components) {
    1839                                         dn->invalid = true;
     1944                                        ldb_dn_mark_invalid(dn);
    18401945                                        return LDB_ERR_OPERATIONS_ERROR;
    18411946                                }
    1842                                 return LDB_SUCCESS;
    1843                         }
    1844                 }
    1845         }
     1947                        }
     1948                        LDB_FREE(dn->ext_linearized);
     1949
     1950                        return LDB_SUCCESS;
     1951                }
     1952        }
     1953
     1954        if (val == NULL) {
     1955                /* removing a value that doesn't exist is not an error */
     1956                return LDB_SUCCESS;
     1957        }
     1958
     1959        v2 = *val;
    18461960
    18471961        p = dn->ext_components
     
    18511965                                 dn->ext_comp_num + 1);
    18521966        if (!dn->ext_components) {
    1853                 dn->invalid = true;
     1967                ldb_dn_mark_invalid(dn);
    18541968                return LDB_ERR_OPERATIONS_ERROR;
    18551969        }
    18561970
    1857         p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, val);
     1971        p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, &v2);
    18581972        p[dn->ext_comp_num].name = talloc_strdup(p, name);
    18591973
    18601974        if (!dn->ext_components[i].name || !dn->ext_components[i].value.data) {
    1861                 dn->invalid = true;
     1975                ldb_dn_mark_invalid(dn);
    18621976                return LDB_ERR_OPERATIONS_ERROR;
    18631977        }
     
    18651979        dn->ext_comp_num++;
    18661980
     1981        LDB_FREE(dn->ext_linearized);
     1982
    18671983        return LDB_SUCCESS;
    18681984}
     
    18701986void ldb_dn_remove_extended_components(struct ldb_dn *dn)
    18711987{
     1988        LDB_FREE(dn->ext_linearized);
     1989        LDB_FREE(dn->ext_components);
    18721990        dn->ext_comp_num = 0;
    1873         LDB_FREE(dn->ext_components);
    18741991}
    18751992
     
    19062023        return false;
    19072024}
     2025
     2026/*
     2027  this updates dn->components, taking the components from ref_dn.
     2028  This is used by code that wants to update the DN path of a DN
     2029  while not impacting on the extended DN components
     2030 */
     2031int ldb_dn_update_components(struct ldb_dn *dn, const struct ldb_dn *ref_dn)
     2032{
     2033        dn->components = talloc_realloc(dn, dn->components,
     2034                                        struct ldb_dn_component, ref_dn->comp_num);
     2035        if (!dn->components) {
     2036                return LDB_ERR_OPERATIONS_ERROR;
     2037        }
     2038        memcpy(dn->components, ref_dn->components,
     2039               sizeof(struct ldb_dn_component)*ref_dn->comp_num);
     2040        dn->comp_num = ref_dn->comp_num;
     2041
     2042        LDB_FREE(dn->casefold);
     2043        LDB_FREE(dn->linearized);
     2044        LDB_FREE(dn->ext_linearized);
     2045
     2046        return LDB_SUCCESS;
     2047}
     2048
     2049/*
     2050  minimise a DN. The caller must pass in a validated DN.
     2051
     2052  If the DN has an extended component then only the first extended
     2053  component is kept, the DN string is stripped.
     2054
     2055  The existing dn is modified
     2056 */
     2057bool ldb_dn_minimise(struct ldb_dn *dn)
     2058{
     2059        unsigned int i;
     2060
     2061        if (!ldb_dn_validate(dn)) {
     2062                return false;
     2063        }
     2064        if (dn->ext_comp_num == 0) {
     2065                return true;
     2066        }
     2067
     2068        /* free components */
     2069        for (i = 0; i < dn->comp_num; i++) {
     2070                LDB_FREE(dn->components[i].name);
     2071                LDB_FREE(dn->components[i].value.data);
     2072                LDB_FREE(dn->components[i].cf_name);
     2073                LDB_FREE(dn->components[i].cf_value.data);
     2074        }
     2075        dn->comp_num = 0;
     2076        dn->valid_case = false;
     2077
     2078        LDB_FREE(dn->casefold);
     2079        LDB_FREE(dn->linearized);
     2080
     2081        /* note that we don't free dn->components as this there are
     2082         * several places in ldb_dn.c that rely on it being non-NULL
     2083         * for an exploded DN
     2084         */
     2085
     2086        for (i = 1; i < dn->ext_comp_num; i++) {
     2087                LDB_FREE(dn->ext_components[i].name);
     2088                LDB_FREE(dn->ext_components[i].value.data);
     2089        }
     2090        dn->ext_comp_num = 1;
     2091
     2092        dn->ext_components = talloc_realloc(dn, dn->ext_components, struct ldb_dn_ext_component, 1);
     2093        if (dn->ext_components == NULL) {
     2094                ldb_dn_mark_invalid(dn);
     2095                return false;
     2096        }
     2097
     2098        LDB_FREE(dn->ext_linearized);
     2099
     2100        return true;
     2101}
  • trunk/server/source4/lib/ldb/common/ldb_ldif.c

    r414 r745  
    4242 
    4343*/
    44 static int ldb_read_data_file(void *mem_ctx, struct ldb_val *value)
     44static int ldb_read_data_file(TALLOC_CTX *mem_ctx, struct ldb_val *value)
    4545{
    4646        struct stat statbuf;
     
    151151  caller frees
    152152*/
    153 char *ldb_base64_encode(void *mem_ctx, const char *buf, int len)
     153char *ldb_base64_encode(TALLOC_CTX *mem_ctx, const char *buf, int len)
    154154{
    155155        const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     
    191191        uint8_t *p = val->data;
    192192
    193         if (ldb->flags & LDB_FLG_SHOW_BINARY) {
    194                 return 0;
    195         }
    196 
    197193        if (val->length == 0) {
    198194                return 0;
     
    220216                        const char *buf, size_t length, int start_pos)
    221217{
    222         unsigned int i;
     218        size_t i;
    223219        int total=0, ret;
    224220
     
    334330                for (j=0;j<msg->elements[i].num_values;j++) {
    335331                        struct ldb_val v;
     332                        bool use_b64_encode;
    336333                        ret = a->syntax->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v);
    337334                        if (ret != LDB_SUCCESS) {
    338335                                v = msg->elements[i].values[j];
    339336                        }
    340                         if (ret != LDB_SUCCESS || ldb_should_b64_encode(ldb, &v)) {
     337                        use_b64_encode = !(ldb->flags & LDB_FLG_SHOW_BINARY)
     338                                        && ldb_should_b64_encode(ldb, &v);
     339                        if (ret != LDB_SUCCESS || use_b64_encode) {
    341340                                ret = fprintf_fn(private_data, "%s:: ",
    342341                                                 msg->elements[i].name);
     
    374373        CHECK_RET;
    375374
     375        talloc_free(mem_ctx);
     376
    376377        return total;
    377378}
     
    448449
    449450/* simple ldif attribute parser */
    450 static int next_attr(void *mem_ctx, char **s, const char **attr, struct ldb_val *value)
     451static int next_attr(TALLOC_CTX *mem_ctx, char **s, const char **attr, struct ldb_val *value)
    451452{
    452453        char *p;
     
    509510                int len = ldb_read_data_file(mem_ctx, value);
    510511                if (len == -1) {
    511                         /* an error occured hile trying to retrieve the file */
     512                        /* an error occurred while trying to retrieve the file */
    512513                        return -1;
    513514                }
  • trunk/server/source4/lib/ldb/common/ldb_match.c

    r414 r745  
    8282                             const struct ldb_message *msg,
    8383                             const struct ldb_parse_tree *tree,
    84                              enum ldb_scope scope)
    85 {
     84                             enum ldb_scope scope, bool *matched)
     85{
     86        const struct ldb_schema_attribute *a;
     87        struct ldb_message_element *el;
     88
    8689        if (ldb_attr_dn(tree->u.present.attr) == 0) {
    87                 return 1;
    88         }
    89 
    90         if (ldb_msg_find_element(msg, tree->u.present.attr)) {
    91                 return 1;
    92         }
    93 
    94         return 0;
     90                *matched = true;
     91                return LDB_SUCCESS;
     92        }
     93
     94        el = ldb_msg_find_element(msg, tree->u.present.attr);
     95        if (el == NULL) {
     96                *matched = false;
     97                return LDB_SUCCESS;
     98        }
     99
     100        a = ldb_schema_attribute_by_name(ldb, el->name);
     101        if (!a) {
     102                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     103        }
     104
     105        if (a->syntax->operator_fn) {
     106                unsigned int i;
     107                for (i = 0; i < el->num_values; i++) {
     108                        int ret = a->syntax->operator_fn(ldb, LDB_OP_PRESENT, a, &el->values[i], NULL, matched);
     109                        if (ret != LDB_SUCCESS) return ret;
     110                        if (*matched) return LDB_SUCCESS;
     111                }
     112                *matched = false;
     113                return LDB_SUCCESS;
     114        }
     115
     116        *matched = true;
     117        return LDB_SUCCESS;
    95118}
    96119
     
    99122                                const struct ldb_parse_tree *tree,
    100123                                enum ldb_scope scope,
    101                                 enum ldb_parse_op comp_op)
     124                                enum ldb_parse_op comp_op, bool *matched)
    102125{
    103126        unsigned int i;
    104127        struct ldb_message_element *el;
    105128        const struct ldb_schema_attribute *a;
    106         int ret;
    107129
    108130        /* FIXME: APPROX comparison not handled yet */
    109         if (comp_op == LDB_OP_APPROX) return 0;
     131        if (comp_op == LDB_OP_APPROX) {
     132                return LDB_ERR_INAPPROPRIATE_MATCHING;
     133        }
    110134
    111135        el = ldb_msg_find_element(msg, tree->u.comparison.attr);
    112136        if (el == NULL) {
    113                 return 0;
     137                *matched = false;
     138                return LDB_SUCCESS;
    114139        }
    115140
    116141        a = ldb_schema_attribute_by_name(ldb, el->name);
     142        if (!a) {
     143                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     144        }
    117145
    118146        for (i = 0; i < el->num_values; i++) {
    119                 ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value);
    120 
    121                 if (ret == 0) {
    122                         return 1;
    123                 }
    124                 if (ret > 0 && comp_op == LDB_OP_GREATER) {
    125                         return 1;
    126                 }
    127                 if (ret < 0 && comp_op == LDB_OP_LESS) {
    128                         return 1;
    129                 }
    130         }
    131 
    132         return 0;
     147                if (a->syntax->operator_fn) {
     148                        int ret;
     149                        ret = a->syntax->operator_fn(ldb, comp_op, a, &el->values[i], &tree->u.comparison.value, matched);
     150                        if (ret != LDB_SUCCESS) return ret;
     151                        if (*matched) return LDB_SUCCESS;
     152                } else {
     153                        int ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value);
     154
     155                        if (ret == 0) {
     156                                *matched = true;
     157                                return LDB_SUCCESS;
     158                        }
     159                        if (ret > 0 && comp_op == LDB_OP_GREATER) {
     160                                *matched = true;
     161                                return LDB_SUCCESS;
     162                        }
     163                        if (ret < 0 && comp_op == LDB_OP_LESS) {
     164                                *matched = true;
     165                                return LDB_SUCCESS;
     166                        }
     167                }
     168        }
     169
     170        *matched = false;
     171        return LDB_SUCCESS;
    133172}
    134173
     
    139178                              const struct ldb_message *msg,
    140179                              const struct ldb_parse_tree *tree,
    141                               enum ldb_scope scope)
     180                              enum ldb_scope scope,
     181                              bool *matched)
    142182{
    143183        unsigned int i;
     
    150190                valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value);
    151191                if (valuedn == NULL) {
    152                         return 0;
     192                        return LDB_ERR_INVALID_DN_SYNTAX;
    153193                }
    154194
     
    157197                talloc_free(valuedn);
    158198
    159                 if (ret == 0) return 1;
    160                 return 0;
     199                *matched = (ret == 0);
     200                return LDB_SUCCESS;
    161201        }
    162202
     
    165205        el = ldb_msg_find_element(msg, tree->u.equality.attr);
    166206        if (el == NULL) {
    167                 return 0;
     207                *matched = false;
     208                return LDB_SUCCESS;
    168209        }
    169210
    170211        a = ldb_schema_attribute_by_name(ldb, el->name);
     212        if (a == NULL) {
     213                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     214        }
    171215
    172216        for (i=0;i<el->num_values;i++) {
    173                 if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value,
    174                                              &el->values[i]) == 0) {
    175                         return 1;
    176                 }
    177         }
    178 
    179         return 0;
     217                if (a->syntax->operator_fn) {
     218                        ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
     219                                                     &tree->u.equality.value, &el->values[i], matched);
     220                        if (ret != LDB_SUCCESS) return ret;
     221                        if (*matched) return LDB_SUCCESS;
     222                } else {
     223                        if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value,
     224                                                     &el->values[i]) == 0) {
     225                                *matched = true;
     226                                return LDB_SUCCESS;
     227                        }
     228                }
     229        }
     230
     231        *matched = false;
     232        return LDB_SUCCESS;
    180233}
    181234
    182235static int ldb_wildcard_compare(struct ldb_context *ldb,
    183236                                const struct ldb_parse_tree *tree,
    184                                 const struct ldb_val value)
     237                                const struct ldb_val value, bool *matched)
    185238{
    186239        const struct ldb_schema_attribute *a;
     
    190243        char *p, *g;
    191244        uint8_t *save_p = NULL;
    192         int c = 0;
     245        unsigned int c = 0;
    193246
    194247        a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr);
    195 
    196         if(a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0)
    197                 return -1;
     248        if (!a) {
     249                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     250        }
     251
     252        if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) {
     253                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     254        }
    198255
    199256        save_p = val.data;
     
    203260
    204261                chunk = tree->u.substring.chunks[c];
    205                 if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;
     262                if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch;
    206263
    207264                /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
    208265                if (cnk.length > val.length) {
    209                         goto failed;
    210                 }
    211                 if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto failed;
     266                        goto mismatch;
     267                }
     268                if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto mismatch;
    212269                val.length -= cnk.length;
    213270                val.data += cnk.length;
     
    220277
    221278                chunk = tree->u.substring.chunks[c];
    222                 if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;
     279                if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch;
    223280
    224281                /* FIXME: case of embedded nulls */
    225282                p = strstr((char *)val.data, (char *)cnk.data);
    226                 if (p == NULL) goto failed;
     283                if (p == NULL) goto mismatch;
    227284                if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) {
    228285                        do { /* greedy */
     
    238295        }
    239296
    240         if ( (! tree->u.substring.end_with_wildcard) && (*(val.data) != 0) ) goto failed; /* last chunk have not reached end of string */
     297        /* last chunk may not have reached end of string */
     298        if ( (! tree->u.substring.end_with_wildcard) && (*(val.data) != 0) ) goto mismatch;
    241299        talloc_free(save_p);
    242         return 1;
    243 
    244 failed:
     300        *matched = true;
     301        return LDB_SUCCESS;
     302
     303mismatch:
     304        *matched = false;
    245305        talloc_free(save_p);
    246306        talloc_free(cnk.data);
    247         return 0;
     307        return LDB_SUCCESS;
    248308}
    249309
     
    254314                               const struct ldb_message *msg,
    255315                               const struct ldb_parse_tree *tree,
    256                                enum ldb_scope scope)
     316                               enum ldb_scope scope, bool *matched)
    257317{
    258318        unsigned int i;
     
    261321        el = ldb_msg_find_element(msg, tree->u.substring.attr);
    262322        if (el == NULL) {
    263                 return 0;
     323                *matched = false;
     324                return LDB_SUCCESS;
    264325        }
    265326
    266327        for (i = 0; i < el->num_values; i++) {
    267                 if (ldb_wildcard_compare(ldb, tree, el->values[i]) == 1) {
    268                         return 1;
    269                 }
    270         }
    271 
    272         return 0;
     328                int ret;
     329                ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched);
     330                if (ret != LDB_SUCCESS) return ret;
     331                if (*matched) return LDB_SUCCESS;
     332        }
     333
     334        *matched = false;
     335        return LDB_SUCCESS;
    273336}
    274337
     
    277340  bitwise-and comparator
    278341*/
    279 static int ldb_comparator_and(const struct ldb_val *v1, const struct ldb_val *v2)
     342static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2,
     343                                  bool *matched)
    280344{
    281345        uint64_t i1, i2;
    282         i1 = strtoull((char *)v1->data, NULL, 0);
    283         i2 = strtoull((char *)v2->data, NULL, 0);
    284         return ((i1 & i2) == i2);
    285 }
    286 
    287 /*
    288   bitwise-or comparator
    289 */
    290 static int ldb_comparator_or(const struct ldb_val *v1, const struct ldb_val *v2)
    291 {
    292         uint64_t i1, i2;
    293         i1 = strtoull((char *)v1->data, NULL, 0);
    294         i2 = strtoull((char *)v2->data, NULL, 0);
    295         return ((i1 & i2) != 0);
     346        char ibuf[100];
     347        char *endptr = NULL;
     348
     349        if (v1->length >= sizeof(ibuf)-1) {
     350                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     351        }
     352        memcpy(ibuf, (char *)v1->data, v1->length);
     353        ibuf[v1->length] = 0;
     354        i1 = strtoull(ibuf, &endptr, 0);
     355        if (endptr != NULL) {
     356                if (endptr == ibuf || *endptr != 0) {
     357                        return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     358                }
     359        }
     360
     361        if (v2->length >= sizeof(ibuf)-1) {
     362                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     363        }
     364        endptr = NULL;
     365        memcpy(ibuf, (char *)v2->data, v2->length);
     366        ibuf[v2->length] = 0;
     367        i2 = strtoull(ibuf, &endptr, 0);
     368        if (endptr != NULL) {
     369                if (endptr == ibuf || *endptr != 0) {
     370                        return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     371                }
     372        }
     373        if (strcmp(LDB_OID_COMPARATOR_AND, oid) == 0) {
     374                *matched = ((i1 & i2) == i2);
     375        } else if (strcmp(LDB_OID_COMPARATOR_OR, oid) == 0) {
     376                *matched = ((i1 & i2) != 0);
     377        } else {
     378                return LDB_ERR_INAPPROPRIATE_MATCHING;
     379        }
     380        return LDB_SUCCESS;
    296381}
    297382
     
    303388                              const struct ldb_message *msg,
    304389                              const struct ldb_parse_tree *tree,
    305                               enum ldb_scope scope)
    306 {
    307         int i;
     390                              enum ldb_scope scope, bool *matched)
     391{
     392        unsigned int i;
    308393        const struct {
    309394                const char *oid;
    310                 int (*comparator)(const struct ldb_val *, const struct ldb_val *);
     395                int (*comparator)(const char *, const struct ldb_val *, const struct ldb_val *, bool *);
    311396        } rules[] = {
    312                 { LDB_OID_COMPARATOR_AND, ldb_comparator_and},
    313                 { LDB_OID_COMPARATOR_OR, ldb_comparator_or}
     397                { LDB_OID_COMPARATOR_AND, ldb_comparator_bitmask},
     398                { LDB_OID_COMPARATOR_OR, ldb_comparator_bitmask}
    314399        };
    315         int (*comp)(const struct ldb_val *, const struct ldb_val *) = NULL;
     400        int (*comp)(const char *,const struct ldb_val *, const struct ldb_val *, bool *) = NULL;
    316401        struct ldb_message_element *el;
    317402
    318403        if (tree->u.extended.dnAttributes) {
    319                 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: dnAttributes extended match not supported yet");
    320                 return -1;
     404                /* FIXME: We really need to find out what this ":dn" part in
     405                 * an extended match means and how to handle it. For now print
     406                 * only a warning to have s3 winbind and other tools working
     407                 * against us. - Matthias */
     408                ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb: dnAttributes extended match not supported yet");
    321409        }
    322410        if (tree->u.extended.rule_id == NULL) {
    323411                ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet");
    324                 return -1;
     412                return LDB_ERR_INAPPROPRIATE_MATCHING;
    325413        }
    326414        if (tree->u.extended.attr == NULL) {
    327415                ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet");
    328                 return -1;
     416                return LDB_ERR_INAPPROPRIATE_MATCHING;
    329417        }
    330418
     
    338426                ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s",
    339427                          tree->u.extended.rule_id);
    340                 return -1;
     428                return LDB_ERR_INAPPROPRIATE_MATCHING;
    341429        }
    342430
     
    344432        el = ldb_msg_find_element(msg, tree->u.extended.attr);
    345433        if (el == NULL) {
    346                 return 0;
     434                *matched = false;
     435                return LDB_SUCCESS;
    347436        }
    348437
    349438        for (i=0;i<el->num_values;i++) {
    350                 int ret = comp(&el->values[i], &tree->u.extended.value);
    351                 if (ret == -1 || ret == 1) return ret;
    352         }
    353 
    354         return 0;
     439                int ret = comp(tree->u.extended.rule_id, &el->values[i], &tree->u.extended.value, matched);
     440                if (ret != LDB_SUCCESS) return ret;
     441                if (*matched) return LDB_SUCCESS;
     442        }
     443
     444        *matched = false;
     445        return LDB_SUCCESS;
    355446}
    356447
     
    366457                             const struct ldb_message *msg,
    367458                             const struct ldb_parse_tree *tree,
    368                              enum ldb_scope scope)
     459                             enum ldb_scope scope, bool *matched)
    369460{
    370461        unsigned int i;
    371         int v;
     462        int ret;
     463
     464        *matched = false;
    372465
    373466        switch (tree->operation) {
    374467        case LDB_OP_AND:
    375468                for (i=0;i<tree->u.list.num_elements;i++) {
    376                         v = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope);
    377                         if (!v) return 0;
    378                 }
    379                 return 1;
     469                        ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
     470                        if (ret != LDB_SUCCESS) return ret;
     471                        if (!*matched) return LDB_SUCCESS;
     472                }
     473                *matched = true;
     474                return LDB_SUCCESS;
    380475
    381476        case LDB_OP_OR:
    382477                for (i=0;i<tree->u.list.num_elements;i++) {
    383                         v = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope);
    384                         if (v) return 1;
    385                 }
    386                 return 0;
     478                        ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
     479                        if (ret != LDB_SUCCESS) return ret;
     480                        if (*matched) return LDB_SUCCESS;
     481                }
     482                *matched = false;
     483                return LDB_SUCCESS;
    387484
    388485        case LDB_OP_NOT:
    389                 return ! ldb_match_message(ldb, msg, tree->u.isnot.child, scope);
     486                ret = ldb_match_message(ldb, msg, tree->u.isnot.child, scope, matched);
     487                if (ret != LDB_SUCCESS) return ret;
     488                *matched = ! *matched;
     489                return LDB_SUCCESS;
    390490
    391491        case LDB_OP_EQUALITY:
    392                 return ldb_match_equality(ldb, msg, tree, scope);
     492                return ldb_match_equality(ldb, msg, tree, scope, matched);
    393493
    394494        case LDB_OP_SUBSTRING:
    395                 return ldb_match_substring(ldb, msg, tree, scope);
     495                return ldb_match_substring(ldb, msg, tree, scope, matched);
    396496
    397497        case LDB_OP_GREATER:
    398                 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER);
     498                return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER, matched);
    399499
    400500        case LDB_OP_LESS:
    401                 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS);
     501                return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS, matched);
    402502
    403503        case LDB_OP_PRESENT:
    404                 return ldb_match_present(ldb, msg, tree, scope);
     504                return ldb_match_present(ldb, msg, tree, scope, matched);
    405505
    406506        case LDB_OP_APPROX:
    407                 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX);
     507                return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX, matched);
    408508
    409509        case LDB_OP_EXTENDED:
    410                 return ldb_match_extended(ldb, msg, tree, scope);
    411 
    412         }
    413 
    414         return 0;
     510                return ldb_match_extended(ldb, msg, tree, scope, matched);
     511        }
     512
     513        return LDB_ERR_INAPPROPRIATE_MATCHING;
    415514}
    416515
     
    421520                  enum ldb_scope scope)
    422521{
     522        bool matched;
     523        int ret;
     524
    423525        if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
    424526                return 0;
    425527        }
    426528
    427         return ldb_match_message(ldb, msg, tree, scope);
    428 }
     529        ret = ldb_match_message(ldb, msg, tree, scope, &matched);
     530        if (ret != LDB_SUCCESS) {
     531                /* to match the old API, we need to consider this a
     532                   failure to match */
     533                return 0;
     534        }
     535        return matched?1:0;
     536}
     537
     538int ldb_match_msg_error(struct ldb_context *ldb,
     539                        const struct ldb_message *msg,
     540                        const struct ldb_parse_tree *tree,
     541                        struct ldb_dn *base,
     542                        enum ldb_scope scope,
     543                        bool *matched)
     544{
     545        if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
     546                *matched = false;
     547                return LDB_SUCCESS;
     548        }
     549
     550        return ldb_match_message(ldb, msg, tree, scope, matched);
     551}
     552
     553int ldb_match_msg_objectclass(const struct ldb_message *msg,
     554                              const char *objectclass)
     555{
     556        unsigned int i;
     557        struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass");
     558        if (!el) {
     559                return 0;
     560        }
     561        for (i=0; i < el->num_values; i++) {
     562                if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) {
     563                        return 1;
     564                }
     565        }
     566        return 0;
     567}
     568
     569
     570                             
  • trunk/server/source4/lib/ldb/common/ldb_modules.c

    r414 r745  
    3434#include "ldb_private.h"
    3535#include "dlinklist.h"
    36 
    37 #define LDB_MODULE_PREFIX       "modules:"
    38 #define LDB_MODULE_PREFIX_LEN   8
    39 
    40 static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name,
    41                                  const char *symbol);
    42 
    43 void ldb_set_modules_dir(struct ldb_context *ldb, const char *path)
    44 {
    45         talloc_free(ldb->modules_dir);
    46         ldb->modules_dir = talloc_strdup(ldb, path);
    47 }
     36#include "system/dir.h"
    4837
    4938static char *ldb_modules_strdup_no_spaces(TALLOC_CTX *mem_ctx, const char *string)
    5039{
    51         int i, len;
     40        size_t i, len;
    5241        char *trimmed;
    5342
     
    8069        const char **m;
    8170        char *modstr, *p;
    82         int i;
     71        unsigned int i;
    8372
    8473        /* spaces not admitted */
     
    9685        }
    9786        talloc_steal(modules, modstr);
     87
     88        if (modstr[0] == '\0') {
     89                modules[0] = NULL;
     90                m = (const char **)modules;
     91                return m;
     92        }
    9893
    9994        i = 0;
     
    131126} *registered_modules = NULL;
    132127
    133 static const struct ldb_builtins {
    134         const struct ldb_backend_ops *backend_ops;
    135         const struct ldb_module_ops *module_ops;
    136 } builtins[];
    137 
    138 static ldb_connect_fn ldb_find_backend(const char *url)
     128static struct backends_list_entry *ldb_find_backend(const char *url_prefix)
    139129{
    140130        struct backends_list_entry *backend;
    141         int i;
    142 
    143         for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {
    144                 if (builtins[i].backend_ops == NULL) continue;
    145 
    146                 if (strncmp(builtins[i].backend_ops->name, url,
    147                             strlen(builtins[i].backend_ops->name)) == 0) {
    148                         return builtins[i].backend_ops->connect_fn;
    149                 }
    150         }
    151131
    152132        for (backend = ldb_backends; backend; backend = backend->next) {
    153                 if (strncmp(backend->ops->name, url,
    154                             strlen(backend->ops->name)) == 0) {
    155                         return backend->ops->connect_fn;
     133                if (strcmp(backend->ops->name, url_prefix) == 0) {
     134                        return backend;
    156135                }
    157136        }
     
    161140
    162141/*
    163  register a new ldb backend
     142  register a new ldb backend
     143
     144  if override is true, then override any existing backend for this prefix
    164145*/
    165 int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn)
    166 {
    167         struct ldb_backend_ops *backend;
    168         struct backends_list_entry *entry;
    169 
    170         backend = talloc(talloc_autofree_context(), struct ldb_backend_ops);
    171         if (!backend) return LDB_ERR_OPERATIONS_ERROR;
    172 
    173         entry = talloc(talloc_autofree_context(), struct backends_list_entry);
    174         if (!entry) {
    175                 talloc_free(backend);
    176                 return LDB_ERR_OPERATIONS_ERROR;
    177         }
    178 
    179         if (ldb_find_backend(url_prefix)) {
    180                 return LDB_SUCCESS;
    181         }
    182 
    183         /* Maybe check for duplicity here later on? */
    184 
    185         backend->name = talloc_strdup(backend, url_prefix);
    186         backend->connect_fn = connectfn;
    187         entry->ops = backend;
    188         DLIST_ADD(ldb_backends, entry);
     146int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn, bool override)
     147{
     148        struct backends_list_entry *be;
     149
     150        be = ldb_find_backend(url_prefix);
     151        if (be) {
     152                if (!override) {
     153                        return LDB_SUCCESS;
     154                }
     155        } else {
     156                be = talloc_zero(ldb_backends, struct backends_list_entry);
     157                if (!be) {
     158                        return LDB_ERR_OPERATIONS_ERROR;
     159                }
     160                be->ops = talloc_zero(be, struct ldb_backend_ops);
     161                if (!be->ops) {
     162                        talloc_free(be);
     163                        return LDB_ERR_OPERATIONS_ERROR;
     164                }
     165                DLIST_ADD_END(ldb_backends, be, struct backends_list_entry);
     166        }
     167
     168        be->ops->name = url_prefix;
     169        be->ops->connect_fn = connectfn;
    189170
    190171        return LDB_SUCCESS;
     
    205186   module may wish to direct certain requests at a particular backend.
    206187*/
    207 int ldb_connect_backend(struct ldb_context *ldb,
    208                         const char *url,
    209                         const char *options[],
    210                         struct ldb_module **backend_module)
     188int ldb_module_connect_backend(struct ldb_context *ldb,
     189                               const char *url,
     190                               const char *options[],
     191                               struct ldb_module **backend_module)
    211192{
    212193        int ret;
    213194        char *backend;
    214         ldb_connect_fn fn;
     195        struct backends_list_entry *be;
    215196
    216197        if (strchr(url, ':') != NULL) {
     
    221202        }
    222203
    223         fn = ldb_find_backend(backend);
    224 
    225         if (fn == NULL) {
    226                 struct ldb_backend_ops *ops;
    227                 char *symbol_name = talloc_asprintf(ldb, "ldb_%s_backend_ops", backend);
    228                 if (symbol_name == NULL) {
    229                         return LDB_ERR_OPERATIONS_ERROR;
    230                 }
    231                 ops = ldb_dso_load_symbol(ldb, backend, symbol_name);
    232                 if (ops != NULL) {
    233                         fn = ops->connect_fn;
    234                 }
    235                 talloc_free(symbol_name);
    236         }
     204        be = ldb_find_backend(backend);
    237205
    238206        talloc_free(backend);
    239207
    240         if (fn == NULL) {
     208        if (be == NULL) {
    241209                ldb_debug(ldb, LDB_DEBUG_FATAL,
    242                           "Unable to find backend for '%s'", url);
     210                          "Unable to find backend for '%s' - do you need to set LDB_MODULES_PATH?", url);
    243211                return LDB_ERR_OTHER;
    244212        }
    245213
    246         ret = fn(ldb, url, ldb->flags, options, backend_module);
     214        ret = be->ops->connect_fn(ldb, url, ldb->flags, options, backend_module);
    247215
    248216        if (ret != LDB_SUCCESS) {
    249217                ldb_debug(ldb, LDB_DEBUG_ERROR,
    250                           "Failed to connect to '%s'", url);
     218                          "Failed to connect to '%s' with backend '%s'", url, be->ops->name);
    251219                return ret;
    252220        }
     
    254222}
    255223
     224static struct ldb_hooks {
     225        struct ldb_hooks *next, *prev;
     226        ldb_hook_fn hook_fn;
     227} *ldb_hooks;
     228
     229/*
     230  register a ldb hook function
     231 */
     232int ldb_register_hook(ldb_hook_fn hook_fn)
     233{
     234        struct ldb_hooks *lc;
     235        lc = talloc_zero(ldb_hooks, struct ldb_hooks);
     236        if (lc == NULL) {
     237                return LDB_ERR_OPERATIONS_ERROR;
     238        }
     239        lc->hook_fn = hook_fn;
     240        DLIST_ADD_END(ldb_hooks, lc, struct ldb_hooks);
     241        return LDB_SUCCESS;
     242}
     243
     244/*
     245  call ldb hooks of a given type
     246 */
     247int ldb_modules_hook(struct ldb_context *ldb, enum ldb_module_hook_type t)
     248{
     249        struct ldb_hooks *lc;
     250        for (lc = ldb_hooks; lc; lc=lc->next) {
     251                int ret = lc->hook_fn(ldb, t);
     252                if (ret != LDB_SUCCESS) {
     253                        return ret;
     254                }
     255        }
     256        return LDB_SUCCESS;
     257}
     258
     259
    256260static const struct ldb_module_ops *ldb_find_module_ops(const char *name)
    257261{
    258262        struct ops_list_entry *e;
    259         int i;
    260 
    261         for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {
    262                 if (builtins[i].module_ops == NULL) continue;
    263 
    264                 if (strcmp(builtins[i].module_ops->name, name) == 0)
    265                         return builtins[i].module_ops;
    266         }
    267263
    268264        for (e = registered_modules; e; e = e->next) {
     
    277273int ldb_register_module(const struct ldb_module_ops *ops)
    278274{
    279         struct ops_list_entry *entry = talloc(talloc_autofree_context(), struct ops_list_entry);
     275        struct ops_list_entry *entry;
    280276
    281277        if (ldb_find_module_ops(ops->name) != NULL)
    282                 return -1;
    283 
     278                return LDB_ERR_ENTRY_ALREADY_EXISTS;
     279
     280        entry = talloc(talloc_autofree_context(), struct ops_list_entry);
    284281        if (entry == NULL)
    285282                return -1;
     
    292289}
    293290
    294 static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name,
    295                                  const char *symbol)
    296 {
    297         char *path;
    298         void *handle;
    299         void *sym;
    300 
    301         if (ldb->modules_dir == NULL)
    302                 return NULL;
    303 
    304         path = talloc_asprintf(ldb, "%s/%s.%s", ldb->modules_dir, name,
    305                                SHLIBEXT);
    306 
    307         ldb_debug(ldb, LDB_DEBUG_TRACE, "trying to load %s from %s", name, path);
    308 
    309         handle = dlopen(path, RTLD_NOW);
    310         if (handle == NULL) {
    311                 ldb_debug(ldb, LDB_DEBUG_WARNING, "unable to load %s from %s: %s", name, path, dlerror());
    312                 return NULL;
    313         }
    314 
    315         sym = (int (*)(void))dlsym(handle, symbol);
    316 
    317         if (sym == NULL) {
    318                 ldb_debug(ldb, LDB_DEBUG_ERROR, "no symbol `%s' found in %s: %s", symbol, path, dlerror());
    319                 return NULL;
    320         }
    321 
    322         talloc_free(path);
    323 
    324         return sym;
    325 }
    326 
    327 int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, struct ldb_module *backend, struct ldb_module **out)
     291/*
     292  load a list of modules
     293 */
     294int ldb_module_load_list(struct ldb_context *ldb, const char **module_list,
     295                         struct ldb_module *backend, struct ldb_module **out)
    328296{
    329297        struct ldb_module *module;
    330         int i;
     298        unsigned int i;
    331299
    332300        module = backend;
    333301
    334         for (i = 0; module_list[i] != NULL; i++) {
     302        for (i = 0; module_list && module_list[i] != NULL; i++) {
    335303                struct ldb_module *current;
    336304                const struct ldb_module_ops *ops;
     
    341309
    342310                ops = ldb_find_module_ops(module_list[i]);
     311
    343312                if (ops == NULL) {
    344                         char *symbol_name = talloc_asprintf(ldb, "ldb_%s_module_ops",
    345                                                                                                 module_list[i]);
    346                         if (symbol_name == NULL) {
    347                                 return LDB_ERR_OPERATIONS_ERROR;
    348                         }
    349                         ops = ldb_dso_load_symbol(ldb, module_list[i], symbol_name);
    350                         talloc_free(symbol_name);
    351                 }
    352 
    353                 if (ops == NULL) {
    354                         ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found",
     313                        ldb_debug(ldb, LDB_DEBUG_FATAL, "WARNING: Module [%s] not found - do you need to set LDB_MODULES_PATH?",
    355314                                  module_list[i]);
    356                         continue;
     315                        return LDB_ERR_OPERATIONS_ERROR;
    357316                }
    358317
     
    372331}
    373332
    374 int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module)
     333/*
     334  initialise a chain of modules
     335 */
     336int ldb_module_init_chain(struct ldb_context *ldb, struct ldb_module *module)
    375337{
    376338        while (module && module->ops->init_context == NULL)
     
    383345                int ret = module->ops->init_context(module);
    384346                if (ret != LDB_SUCCESS) {
    385                         ldb_debug(ldb, LDB_DEBUG_FATAL, "module %s initialization failed", module->ops->name);
     347                        ldb_debug(ldb, LDB_DEBUG_FATAL, "module %s initialization failed : %s",
     348                                  module->ops->name, ldb_strerror(ret));
    386349                        return ret;
    387350                }
     
    393356int ldb_load_modules(struct ldb_context *ldb, const char *options[])
    394357{
     358        const char *modules_string;
    395359        const char **modules = NULL;
    396         int i;
    397360        int ret;
    398361        TALLOC_CTX *mem_ctx = talloc_new(ldb);
     
    405368        /* check if we have a custom module list passd as ldb option */
    406369        if (options) {
    407                 for (i = 0; options[i] != NULL; i++) {
    408                         if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) {
    409                                 modules = ldb_modules_list_from_string(ldb, mem_ctx, &options[i][LDB_MODULE_PREFIX_LEN]);
    410                         }
     370                modules_string = ldb_options_find(ldb, options, "modules");
     371                if (modules_string) {
     372                        modules = ldb_modules_list_from_string(ldb, mem_ctx, modules_string);
    411373                }
    412374        }
     
    454416
    455417        if (modules != NULL) {
    456                 ret = ldb_load_modules_list(ldb, modules, ldb->modules, &ldb->modules);
     418                ret = ldb_module_load_list(ldb, modules, ldb->modules, &ldb->modules);
    457419                if (ret != LDB_SUCCESS) {
    458420                        talloc_free(mem_ctx);
     
    463425        }
    464426
    465         ret = ldb_init_module_chain(ldb, ldb->modules);
     427        ret = ldb_module_init_chain(ldb, ldb->modules);
    466428        talloc_free(mem_ctx);
    467429        return ret;
     
    476438        module = module->next; \
    477439        while (module && module->ops->op == NULL) module = module->next; \
     440        if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { \
     441                ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_trace_next_request: (%s)->" #op, \
     442                          module->ops->name);                           \
     443        }                                                               \
    478444} while (0)
    479445
     
    516482{
    517483        return module->ldb;
     484}
     485
     486const struct ldb_module_ops *ldb_module_get_ops(struct ldb_module *module)
     487{
     488        return module->ops;
    518489}
    519490
     
    592563                 * corner for module developers to cut themselves on
    593564                 */
    594                 ldb_module_done(request, NULL, NULL, ret);
     565                ret = ldb_module_done(request, NULL, NULL, ret);
    595566        }
    596567        return ret;
     
    601572        module = module->next;
    602573
    603         return ldb_init_module_chain(module->ldb, module);
     574        return ldb_module_init_chain(module->ldb, module);
    604575}
    605576
    606577int ldb_next_start_trans(struct ldb_module *module)
    607578{
     579        int ret;
    608580        FIND_OP(module, start_transaction);
    609         return module->ops->start_transaction(module);
     581        ret = module->ops->start_transaction(module);
     582        if (ret == LDB_SUCCESS) {
     583                return ret;
     584        }
     585        if (!ldb_errstring(module->ldb)) {
     586                /* Set a default error string, to place the blame somewhere */
     587                ldb_asprintf_errstring(module->ldb, "start_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
     588        }
     589        if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
     590                ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_start_trans error: %s",
     591                          ldb_errstring(module->ldb));                         
     592        }
     593        return ret;
    610594}
    611595
    612596int ldb_next_end_trans(struct ldb_module *module)
    613597{
     598        int ret;
    614599        FIND_OP(module, end_transaction);
    615         return module->ops->end_transaction(module);
     600        ret = module->ops->end_transaction(module);
     601        if (ret == LDB_SUCCESS) {
     602                return ret;
     603        }
     604        if (!ldb_errstring(module->ldb)) {
     605                /* Set a default error string, to place the blame somewhere */
     606                ldb_asprintf_errstring(module->ldb, "end_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
     607        }
     608        if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
     609                ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_end_trans error: %s",
     610                          ldb_errstring(module->ldb));                         
     611        }
     612        return ret;
    616613}
    617614
    618615int ldb_next_prepare_commit(struct ldb_module *module)
    619616{
     617        int ret;
    620618        FIND_OP_NOERR(module, prepare_commit);
    621619        if (module == NULL) {
     
    624622                return LDB_SUCCESS;
    625623        }
    626         return module->ops->prepare_commit(module);
     624        ret = module->ops->prepare_commit(module);
     625        if (ret == LDB_SUCCESS) {
     626                return ret;
     627        }
     628        if (!ldb_errstring(module->ldb)) {
     629                /* Set a default error string, to place the blame somewhere */
     630                ldb_asprintf_errstring(module->ldb, "prepare_commit error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
     631        }
     632        if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
     633                ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_prepare_commit error: %s",
     634                          ldb_errstring(module->ldb));                         
     635        }
     636        return ret;
    627637}
    628638
    629639int ldb_next_del_trans(struct ldb_module *module)
    630640{
     641        int ret;
    631642        FIND_OP(module, del_transaction);
    632         return module->ops->del_transaction(module);
     643        ret = module->ops->del_transaction(module);
     644        if (ret == LDB_SUCCESS) {
     645                return ret;
     646        }
     647        if (!ldb_errstring(module->ldb)) {
     648                /* Set a default error string, to place the blame somewhere */
     649                ldb_asprintf_errstring(module->ldb, "del_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
     650        }
     651        if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) {
     652                ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_del_trans error: %s",
     653                          ldb_errstring(module->ldb));                         
     654        }
     655        return ret;
    633656}
    634657
     
    647670        h->ldb = ldb;
    648671        h->flags = 0;
     672        h->location = NULL;
     673        h->parent = NULL;
    649674
    650675        return h;
     
    729754 *      ctrls: controls to send in the reply (must be a talloc pointer, steal)
    730755 *      response: results for extended request (steal)
    731  *      error: LDB_SUCCESS for a succesful return
     756 *      error: LDB_SUCCESS for a successful return
    732757 *             any other ldb error otherwise
    733758 */
     
    763788        }
    764789
    765         req->callback(req, ares);
    766         return error;
     790        return req->callback(req, ares);
    767791}
    768792
    769793/* to be used *only* in modules init functions.
    770  * this function i synchronous and will register
     794 * this function is synchronous and will register
    771795 * the requested OID in the rootdse module if present
    772796 * otherwise it will return an error */
     
    801825}
    802826
    803 #ifndef STATIC_LIBLDB_MODULES
    804 
    805 #ifdef HAVE_LDB_LDAP
    806 #define LDAP_BACKEND LDB_BACKEND(ldap), LDB_BACKEND(ldapi), LDB_BACKEND(ldaps),
    807 #else
    808 #define LDAP_BACKEND
     827static int ldb_modules_load_dir(const char *modules_dir, const char *version);
     828
     829
     830/*
     831  load one module. A static list of loaded module inode numbers is
     832  used to prevent a module being loaded twice
     833
     834  dlopen() is used on the module, and dlsym() is then used to look for
     835  a ldb_init_module() function. If present, that function is called
     836  with the ldb version number as an argument.
     837
     838  The ldb_init_module() function will typically call
     839  ldb_register_module() and ldb_register_backend() to register a
     840  module or backend, but it may also be used to register command line
     841  handling functions, ldif handlers or any other local
     842  modififications.
     843
     844  The ldb_init_module() function does not get a ldb_context passed in,
     845  as modules will be used for multiple ldb context handles. The call
     846  from the first ldb_init() is just a convenient way to ensure it is
     847  called early enough.
     848 */
     849static int ldb_modules_load_path(const char *path, const char *version)
     850{
     851        void *handle;
     852        int (*init_fn)(const char *);
     853        int ret;
     854        struct stat st;
     855        static struct loaded {
     856                struct loaded *next, *prev;
     857                ino_t st_ino;
     858                dev_t st_dev;
     859        } *loaded;
     860        struct loaded *le;
     861        int dlopen_flags;
     862
     863        ret = stat(path, &st);
     864        if (ret != 0) {
     865                fprintf(stderr, "ldb: unable to stat module %s : %s\n", path, strerror(errno));
     866                return LDB_ERR_UNAVAILABLE;
     867        }
     868
     869        for (le=loaded; le; le=le->next) {
     870                if (le->st_ino == st.st_ino &&
     871                    le->st_dev == st.st_dev) {
     872                        /* its already loaded */
     873                        return LDB_SUCCESS;
     874                }
     875        }
     876
     877        le = talloc(loaded, struct loaded);
     878        if (le == NULL) {
     879                fprintf(stderr, "ldb: unable to allocated loaded entry\n");
     880                return LDB_ERR_UNAVAILABLE;
     881        }
     882
     883        le->st_ino = st.st_ino;
     884        le->st_dev = st.st_dev;
     885
     886        DLIST_ADD_END(loaded, le, struct loaded);
     887
     888        /* if it is a directory, recurse */
     889        if (S_ISDIR(st.st_mode)) {
     890                return ldb_modules_load_dir(path, version);
     891        }
     892
     893        dlopen_flags = RTLD_NOW;
     894#ifdef RTLD_DEEPBIND
     895        /* use deepbind if possible, to avoid issues with different
     896           system library varients, for example ldb modules may be linked
     897           against Heimdal while the application may use MIT kerberos
     898
     899           See the dlopen manpage for details
     900        */
     901        dlopen_flags |= RTLD_DEEPBIND;
    809902#endif
    810903
    811 #ifdef HAVE_LDB_SQLITE3
    812 #define SQLITE3_BACKEND LDB_BACKEND(sqlite3),
    813 #else
    814 #define SQLITE3_BACKEND
    815 #endif
    816 
    817 #define STATIC_LIBLDB_MODULES \
    818         LDB_BACKEND(tdb),       \
    819         LDAP_BACKEND    \
    820         SQLITE3_BACKEND \
    821         LDB_MODULE(rdn_name),   \
    822         LDB_MODULE(paged_results),      \
    823         LDB_MODULE(server_sort),                \
    824         LDB_MODULE(asq), \
    825         NULL
    826 #endif
    827 
    828 /*
    829  * this is a bit hacked, as STATIC_LIBLDB_MODULES contains ','
    830  * between the elements and we want to autogenerate the
    831  * extern struct declarations, so we do some hacks and let the
    832  * ',' appear in an unused function prototype.
    833  */
    834 #undef NULL
    835 #define NULL LDB_MODULE(NULL),
    836 
    837 #define LDB_BACKEND(name) \
    838         int); \
    839         extern const struct ldb_backend_ops ldb_ ## name ## _backend_ops;\
    840         extern void ldb_noop ## name (int
    841 #define LDB_MODULE(name) \
    842         int); \
    843         extern const struct ldb_module_ops ldb_ ## name ## _module_ops;\
    844         extern void ldb_noop ## name (int
    845 
    846 extern void ldb_start_noop(int,
    847 STATIC_LIBLDB_MODULES
    848 int);
    849 
    850 #undef NULL
    851 #define NULL { \
    852         .backend_ops = (void *)0, \
    853         .module_ops = (void *)0 \
    854 }
    855 
    856 #undef LDB_BACKEND
    857 #define LDB_BACKEND(name) { \
    858         .backend_ops = &ldb_ ## name ## _backend_ops, \
    859         .module_ops = (void *)0 \
    860 }
    861 #undef LDB_MODULE
    862 #define LDB_MODULE(name) { \
    863         .backend_ops = (void *)0, \
    864         .module_ops = &ldb_ ## name ## _module_ops \
    865 }
    866 
    867 static const struct ldb_builtins builtins[] = {
    868         STATIC_LIBLDB_MODULES
    869 };
     904        handle = dlopen(path, dlopen_flags);
     905        if (handle == NULL) {
     906                fprintf(stderr, "ldb: unable to dlopen %s : %s\n", path, dlerror());
     907                return LDB_SUCCESS;
     908        }
     909
     910        init_fn = dlsym(handle, "ldb_init_module");
     911        if (init_fn == NULL) {
     912                /* ignore it, it could be an old-style
     913                 * module. Once we've converted all modules we
     914                 * could consider this an error */
     915                dlclose(handle);
     916                return LDB_SUCCESS;
     917        }
     918
     919        ret = init_fn(version);
     920        if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
     921                /* the module is already registered - ignore this, as
     922                 * it can happen if LDB_MODULES_PATH points at both
     923                 * the build and install directory
     924                 */
     925                ret = LDB_SUCCESS;
     926        }
     927        return ret;
     928}
     929
     930static int qsort_string(const char **s1, const char **s2)
     931{
     932        return strcmp(*s1, *s2);
     933}
     934
     935
     936/*
     937  load all modules from the given ldb modules directory. This is run once
     938  during the first ldb_init() call.
     939
     940  Modules are loaded in alphabetical order to ensure that any module
     941  load ordering dependencies are reproducible. Modules should avoid
     942  relying on load order
     943 */
     944static int ldb_modules_load_dir(const char *modules_dir, const char *version)
     945{
     946        DIR *dir;
     947        struct dirent *de;
     948        const char **modlist = NULL;
     949        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
     950        unsigned i, num_modules = 0;
     951
     952        dir = opendir(modules_dir);
     953        if (dir == NULL) {
     954                if (errno == ENOENT) {
     955                        talloc_free(tmp_ctx);
     956                        /* we don't have any modules */
     957                        return LDB_SUCCESS;
     958                }
     959                talloc_free(tmp_ctx);
     960                fprintf(stderr, "ldb: unable to open modules directory '%s' - %s\n",
     961                        modules_dir, strerror(errno));
     962                return LDB_ERR_UNAVAILABLE;
     963        }
     964
     965
     966        while ((de = readdir(dir))) {
     967                if (ISDOT(de->d_name) || ISDOTDOT(de->d_name))
     968                        continue;
     969
     970                modlist = talloc_realloc(tmp_ctx, modlist, const char *, num_modules+1);
     971                if (modlist == NULL) {
     972                        talloc_free(tmp_ctx);
     973                        closedir(dir);
     974                        fprintf(stderr, "ldb: unable to allocate modules list\n");
     975                        return LDB_ERR_UNAVAILABLE;
     976                }
     977                modlist[num_modules] = talloc_asprintf(modlist, "%s/%s", modules_dir, de->d_name);
     978                if (modlist[num_modules] == NULL) {
     979                        talloc_free(tmp_ctx);
     980                        closedir(dir);
     981                        fprintf(stderr, "ldb: unable to allocate module list entry\n");
     982                        return LDB_ERR_UNAVAILABLE;
     983                }
     984                num_modules++;
     985        }
     986
     987        closedir(dir);
     988
     989        /* sort the directory, so we get consistent load ordering */
     990        TYPESAFE_QSORT(modlist, num_modules, qsort_string);
     991
     992        for (i=0; i<num_modules; i++) {
     993                int ret = ldb_modules_load_path(modlist[i], version);
     994                if (ret != LDB_SUCCESS) {
     995                        fprintf(stderr, "ldb: failed to initialise module %s : %s\n",
     996                                modlist[i], ldb_strerror(ret));
     997                        talloc_free(tmp_ctx);
     998                        return ret;
     999                }
     1000        }
     1001
     1002        talloc_free(tmp_ctx);
     1003
     1004        return LDB_SUCCESS;
     1005}
     1006
     1007/*
     1008   load any additional modules from the given directory
     1009*/
     1010void ldb_set_modules_dir(struct ldb_context *ldb, const char *path)
     1011{
     1012        int ret = ldb_modules_load_path(path, LDB_VERSION);
     1013        if (ret != LDB_SUCCESS) {
     1014                ldb_asprintf_errstring(ldb, "Failed to load modules from: %s\n", path);
     1015        }
     1016}
     1017
     1018
     1019/*
     1020  load all modules static (builtin) modules
     1021 */
     1022static int ldb_modules_load_static(const char *version)
     1023{
     1024        static bool initialised;
     1025#define _MODULE_PROTO(init) extern int init(const char *);
     1026        STATIC_ldb_MODULES_PROTO;
     1027        const ldb_module_init_fn static_init_functions[] = { STATIC_ldb_MODULES };
     1028        unsigned i;
     1029
     1030        if (initialised) {
     1031                return LDB_SUCCESS;
     1032        }
     1033        initialised = true;
     1034
     1035        for (i=0; static_init_functions[i]; i++) {
     1036                int ret = static_init_functions[i](version);
     1037                if (ret != LDB_SUCCESS) {
     1038                        return ret;
     1039                }
     1040        }
     1041        return LDB_SUCCESS;
     1042}
     1043
     1044/*
     1045  load all modules from the given ldb modules path, colon
     1046  separated.
     1047
     1048  modules are loaded recursively for all subdirectories in the paths
     1049 */
     1050int ldb_modules_load(const char *modules_path, const char *version)
     1051{
     1052        char *tok, *path, *tok_ptr=NULL;
     1053        int ret;
     1054
     1055        ret = ldb_modules_load_static(version);
     1056        if (ret != LDB_SUCCESS) {
     1057                return ret;
     1058        }
     1059
     1060        path = talloc_strdup(NULL, modules_path);
     1061        if (path == NULL) {
     1062                fprintf(stderr, "ldb: failed to allocate modules_path\n");
     1063                return LDB_ERR_UNAVAILABLE;
     1064        }
     1065
     1066        for (tok=strtok_r(path, ":", &tok_ptr);
     1067             tok;
     1068             tok=strtok_r(NULL, ":", &tok_ptr)) {
     1069                ret = ldb_modules_load_path(tok, version);
     1070                if (ret != LDB_SUCCESS) {
     1071                        talloc_free(path);
     1072                        return ret;
     1073                }
     1074        }
     1075        talloc_free(path);
     1076
     1077        return LDB_SUCCESS;
     1078}
     1079
     1080
     1081/*
     1082  return a string representation of the calling chain for the given
     1083  ldb request
     1084 */
     1085char *ldb_module_call_chain(struct ldb_request *req, TALLOC_CTX *mem_ctx)
     1086{
     1087        char *ret;
     1088        int i=0;
     1089
     1090        ret = talloc_strdup(mem_ctx, "");
     1091        if (ret == NULL) {
     1092                return NULL;
     1093        }
     1094
     1095        while (req && req->handle) {
     1096                char *s = talloc_asprintf_append_buffer(ret, "req[%u] %p  : %s\n",
     1097                                                        i++, req, ldb_req_location(req));
     1098                if (s == NULL) {
     1099                        talloc_free(ret);
     1100                        return NULL;
     1101                }
     1102                ret = s;
     1103                req = req->handle->parent;
     1104        }
     1105        return ret;
     1106}
     1107
     1108
     1109/*
     1110  return the next module in the chain
     1111 */
     1112struct ldb_module *ldb_module_next(struct ldb_module *module)
     1113{
     1114        return module->next;
     1115}
     1116
     1117/*
     1118  set the next module in the module chain
     1119 */
     1120void ldb_module_set_next(struct ldb_module *module, struct ldb_module *next)
     1121{
     1122        module->next = next;
     1123}
     1124
     1125
     1126/*
     1127  get the popt_options pointer in the ldb structure. This allows a ldb
     1128  module to change the command line parsing
     1129 */
     1130struct poptOption **ldb_module_popt_options(struct ldb_context *ldb)
     1131{
     1132        return &ldb->popt_options;
     1133}
     1134
     1135
     1136/*
     1137  return the current ldb flags LDB_FLG_*
     1138 */
     1139uint32_t ldb_module_flags(struct ldb_context *ldb)
     1140{
     1141        return ldb->flags;
     1142}
  • trunk/server/source4/lib/ldb/common/ldb_msg.c

    r414 r745  
    3737  create a new ldb_message in a given memory context (NULL for top level)
    3838*/
    39 struct ldb_message *ldb_msg_new(void *mem_ctx)
     39struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
    4040{
    4141        return talloc_zero(mem_ctx, struct ldb_message);
     
    6464{
    6565        if (v1->length != v2->length) return 0;
    66 
     66        if (v1->data == v2->data) return 1;
    6767        if (v1->length == 0) return 1;
    6868
     
    9393  duplicate a ldb_val structure
    9494*/
    95 struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
     95struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
    9696{
    9797        struct ldb_val v2;
     
    115115}
    116116
    117 /*
    118   add an empty element to a message
    119 */
    120 int ldb_msg_add_empty(  struct ldb_message *msg,
    121                         const char *attr_name,
    122                         int flags,
    123                         struct ldb_message_element **return_el)
     117/**
     118 * Adds new empty element to msg->elements
     119 */
     120static int _ldb_msg_add_el(struct ldb_message *msg,
     121                           struct ldb_message_element **return_el)
    124122{
    125123        struct ldb_message_element *els;
    126124
    127         els = talloc_realloc(msg, msg->elements,
    128                              struct ldb_message_element, msg->num_elements+1);
     125        /*
     126         * TODO: Find out a way to assert on input parameters.
     127         * msg and return_el must be valid
     128         */
     129
     130        els = talloc_realloc(msg, msg->elements,
     131                             struct ldb_message_element, msg->num_elements + 1);
    129132        if (!els) {
    130133                errno = ENOMEM;
     
    132135        }
    133136
    134         els[msg->num_elements].values = NULL;
    135         els[msg->num_elements].num_values = 0;
    136         els[msg->num_elements].flags = flags;
    137         els[msg->num_elements].name = talloc_strdup(els, attr_name);
    138         if (!els[msg->num_elements].name) {
     137        ZERO_STRUCT(els[msg->num_elements]);
     138
     139        msg->elements = els;
     140        msg->num_elements++;
     141
     142        *return_el = &els[msg->num_elements-1];
     143
     144        return LDB_SUCCESS;
     145}
     146
     147/**
     148 * Add an empty element with a given name to a message
     149 */
     150int ldb_msg_add_empty(struct ldb_message *msg,
     151                      const char *attr_name,
     152                      int flags,
     153                      struct ldb_message_element **return_el)
     154{
     155        int ret;
     156        struct ldb_message_element *el;
     157
     158        ret = _ldb_msg_add_el(msg, &el);
     159        if (ret != LDB_SUCCESS) {
     160                return ret;
     161        }
     162
     163        /* initialize newly added element */
     164        el->flags = flags;
     165        el->name = talloc_strdup(msg->elements, attr_name);
     166        if (!el->name) {
    139167                errno = ENOMEM;
    140168                return LDB_ERR_OPERATIONS_ERROR;
    141169        }
    142170
    143         msg->elements = els;
    144         msg->num_elements++;
    145 
    146171        if (return_el) {
    147                 *return_el = &els[msg->num_elements-1];
     172                *return_el = el;
    148173        }
    149174
     
    151176}
    152177
    153 /*
    154   add an empty element to a message
    155 */
     178/**
     179 * Adds an element to a message.
     180 *
     181 * NOTE: Ownership of ldb_message_element fields
     182 *       is NOT transferred. Thus, if *el pointer
     183 *       is invalidated for some reason, this will
     184 *       corrupt *msg contents also
     185 */
    156186int ldb_msg_add(struct ldb_message *msg,
    157187                const struct ldb_message_element *el,
    158188                int flags)
    159189{
     190        int ret;
     191        struct ldb_message_element *el_new;
    160192        /* We have to copy this, just in case *el is a pointer into
    161193         * what ldb_msg_add_empty() is about to realloc() */
    162194        struct ldb_message_element el_copy = *el;
    163         if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) {
    164                 return LDB_ERR_OPERATIONS_ERROR;
    165         }
    166 
    167         msg->elements[msg->num_elements-1] = el_copy;
    168         msg->elements[msg->num_elements-1].flags = flags;
     195
     196        ret = _ldb_msg_add_el(msg, &el_new);
     197        if (ret != LDB_SUCCESS) {
     198                return ret;
     199        }
     200
     201        el_new->flags      = flags;
     202        el_new->name       = el_copy.name;
     203        el_new->num_values = el_copy.num_values;
     204        el_new->values     = el_copy.values;
    169205
    170206        return LDB_SUCCESS;
     
    191227        }
    192228
    193         vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
     229        vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
     230                              el->num_values+1);
    194231        if (!vals) {
    195232                errno = ENOMEM;
     
    238275
    239276        if (val.length == 0) {
    240                 /* allow empty strings as non-existant attributes */
     277                /* allow empty strings as non-existent attributes */
    241278                return LDB_SUCCESS;
    242279        }
     
    256293        val.length = strlen(str);
    257294
     295        if (val.length == 0) {
     296                /* allow empty strings as non-existent attributes */
     297                return LDB_SUCCESS;
     298        }
     299
    258300        return ldb_msg_add_steal_value(msg, attr_name, &val);
     301}
     302
     303/*
     304  add a DN element to a message
     305  WARNING: this uses the linearized string from the dn, and does not
     306  copy the string.
     307*/
     308int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
     309                              struct ldb_dn *dn)
     310{
     311        char *str = ldb_dn_alloc_linearized(msg, dn);
     312
     313        if (str == NULL) {
     314                /* we don't want to have unknown DNs added */
     315                return LDB_ERR_OPERATIONS_ERROR;
     316        }
     317
     318        return ldb_msg_add_steal_string(msg, attr_name, str);
    259319}
    260320
     
    283343/*
    284344  compare two ldb_message_element structures
    285   assumes case senistive comparison
     345  assumes case sensitive comparison
    286346*/
    287347int ldb_msg_element_compare(struct ldb_message_element *el1,
     
    342402                                       unsigned int default_value)
    343403{
     404        unsigned int ret;
    344405        const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
    345406        if (!v || !v->data) {
    346407                return default_value;
    347408        }
     409
     410        /* in LDAP there're only int32_t values */
     411        errno = 0;
     412        ret = strtol((const char *)v->data, NULL, 0);
     413        if (errno == 0) {
     414                return ret;
     415        }
     416
    348417        return strtoul((const char *)v->data, NULL, 0);
    349418}
     
    364433                                     uint64_t default_value)
    365434{
     435        uint64_t ret;
    366436        const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
    367437        if (!v || !v->data) {
    368438                return default_value;
    369439        }
     440
     441        /* in LDAP there're only int64_t values */
     442        errno = 0;
     443        ret = strtoll((const char *)v->data, NULL, 0);
     444        if (errno == 0) {
     445                return ret;
     446        }
     447
    370448        return strtoull((const char *)v->data, NULL, 0);
    371449}
     
    411489
    412490struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
    413                                        void *mem_ctx,
     491                                       TALLOC_CTX *mem_ctx,
    414492                                       const struct ldb_message *msg,
    415493                                       const char *attr_name)
     
    435513void ldb_msg_sort_elements(struct ldb_message *msg)
    436514{
    437         qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
    438               (comparison_fn_t)ldb_msg_element_compare_name);
     515        TYPESAFE_QSORT(msg->elements, msg->num_elements,
     516                       ldb_msg_element_compare_name);
    439517}
    440518
     
    447525{
    448526        struct ldb_message *msg2;
    449         int i;
     527        unsigned int i;
    450528
    451529        msg2 = talloc(mem_ctx, struct ldb_message);
     
    477555{
    478556        struct ldb_message *msg2;
    479         int i, j;
     557        unsigned int i, j;
    480558
    481559        msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
     
    507585
    508586
    509 /*
    510   canonicalise a message, merging elements of the same name
    511 */
     587/**
     588 * Canonicalize a message, merging elements of the same name
     589 */
    512590struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
    513591                                         const struct ldb_message *msg)
    514592{
    515         int i;
     593        int ret;
    516594        struct ldb_message *msg2;
    517595
    518         msg2 = ldb_msg_copy(ldb, msg);
    519         if (msg2 == NULL) return NULL;
     596        /*
     597         * Preserve previous behavior and allocate
     598         * *msg2 into *ldb context
     599         */
     600        ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
     601        if (ret != LDB_SUCCESS) {
     602                return NULL;
     603        }
     604
     605        return msg2;
     606}
     607
     608/**
     609 * Canonicalize a message, merging elements of the same name
     610 */
     611int ldb_msg_normalize(struct ldb_context *ldb,
     612                      TALLOC_CTX *mem_ctx,
     613                      const struct ldb_message *msg,
     614                      struct ldb_message **_msg_out)
     615{
     616        unsigned int i;
     617        struct ldb_message *msg2;
     618
     619        msg2 = ldb_msg_copy(mem_ctx, msg);
     620        if (msg2 == NULL) {
     621                return LDB_ERR_OPERATIONS_ERROR;
     622        }
    520623
    521624        ldb_msg_sort_elements(msg2);
    522625
    523         for (i=1;i<msg2->num_elements;i++) {
     626        for (i=1; i < msg2->num_elements; i++) {
    524627                struct ldb_message_element *el1 = &msg2->elements[i-1];
    525628                struct ldb_message_element *el2 = &msg2->elements[i];
     629
    526630                if (ldb_msg_element_compare_name(el1, el2) == 0) {
    527                         el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
    528                                                        el1->num_values + el2->num_values);
    529                         if (el1->values == NULL) {
    530                                 return NULL;
     631                        el1->values = talloc_realloc(msg2->elements,
     632                                                     el1->values, struct ldb_val,
     633                                                     el1->num_values + el2->num_values);
     634                        if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
     635                                talloc_free(msg2);
     636                                return LDB_ERR_OPERATIONS_ERROR;
    531637                        }
    532638                        memcpy(el1->values + el1->num_values,
     
    535641                        el1->num_values += el2->num_values;
    536642                        talloc_free(discard_const_p(char, el2->name));
    537                         if (i+1<msg2->num_elements) {
    538                                 memmove(el2, el2+1, sizeof(struct ldb_message_element) * 
     643                        if ((i+1) < msg2->num_elements) {
     644                                memmove(el2, el2+1, sizeof(struct ldb_message_element) *
    539645                                        (msg2->num_elements - (i+1)));
    540646                        }
     
    544650        }
    545651
    546         return msg2;
    547 }
    548 
    549 
    550 /*
    551   return a ldb_message representing the differences between msg1 and msg2. If you
    552   then use this in a ldb_modify() call it can be used to save edits to a message
    553 */
     652        *_msg_out = msg2;
     653        return LDB_SUCCESS;
     654}
     655
     656
     657/**
     658 * return a ldb_message representing the differences between msg1 and msg2.
     659 * If you then use this in a ldb_modify() call,
     660 * it can be used to save edits to a message
     661 */
    554662struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
    555663                                 struct ldb_message *msg1,
    556664                                 struct ldb_message *msg2)
    557665{
     666        int ldb_ret;
     667        struct ldb_message *mod;
     668
     669        ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
     670        if (ldb_ret != LDB_SUCCESS) {
     671                return NULL;
     672        }
     673
     674        return mod;
     675}
     676
     677/**
     678 * return a ldb_message representing the differences between msg1 and msg2.
     679 * If you then use this in a ldb_modify() call it can be used to save edits to a message
     680 *
     681 * Result message is constructed as follows:
     682 * - LDB_FLAG_MOD_ADD     - elements found only in msg2
     683 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
     684 *                          Value for msg2 element is used
     685 * - LDB_FLAG_MOD_DELETE  - elements found only in msg2
     686 *
     687 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
     688 */
     689int ldb_msg_difference(struct ldb_context *ldb,
     690                       TALLOC_CTX *mem_ctx,
     691                       struct ldb_message *msg1,
     692                       struct ldb_message *msg2,
     693                       struct ldb_message **_msg_out)
     694{
     695        int ldb_res;
     696        unsigned int i;
    558697        struct ldb_message *mod;
    559698        struct ldb_message_element *el;
    560         unsigned int i;
    561 
    562         mod = ldb_msg_new(ldb);
     699        TALLOC_CTX *temp_ctx;
     700
     701        temp_ctx = talloc_new(mem_ctx);
     702        if (!temp_ctx) {
     703                return LDB_ERR_OPERATIONS_ERROR;
     704        }
     705
     706        mod = ldb_msg_new(temp_ctx);
     707        if (mod == NULL) {
     708                goto failed;
     709        }
    563710
    564711        mod->dn = msg1->dn;
     
    566713        mod->elements = NULL;
    567714
    568         msg2 = ldb_msg_canonicalize(ldb, msg2);
    569         if (msg2 == NULL) {
    570                 return NULL;
    571         }
    572        
    573         /* look in msg2 to find elements that need to be added
    574            or modified */
     715        /*
     716         * Canonicalize *msg2 so we have no repeated elements
     717         * Resulting message is allocated in *mod's mem context,
     718         * as we are going to move some elements from *msg2 to
     719         * *mod object later
     720         */
     721        ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
     722        if (ldb_res != LDB_SUCCESS) {
     723                goto failed;
     724        }
     725
     726        /* look in msg2 to find elements that need to be added or modified */
    575727        for (i=0;i<msg2->num_elements;i++) {
    576728                el = ldb_msg_find_element(msg1, msg2->elements[i].name);
     
    580732                }
    581733
    582                 if (ldb_msg_add(mod,
    583                                 &msg2->elements[i],
    584                                 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
    585                         return NULL;
     734                ldb_res = ldb_msg_add(mod,
     735                                      &msg2->elements[i],
     736                                      el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
     737                if (ldb_res != LDB_SUCCESS) {
     738                        goto failed;
    586739                }
    587740        }
     
    590743        for (i=0;i<msg1->num_elements;i++) {
    591744                el = ldb_msg_find_element(msg2, msg1->elements[i].name);
    592                 if (!el) {
    593                         if (ldb_msg_add_empty(mod,
    594                                               msg1->elements[i].name,
    595                                               LDB_FLAG_MOD_DELETE, NULL) != 0) {
    596                                 return NULL;
     745                if (el == NULL) {
     746                        ldb_res = ldb_msg_add_empty(mod,
     747                                                    msg1->elements[i].name,
     748                                                    LDB_FLAG_MOD_DELETE, NULL);
     749                        if (ldb_res != LDB_SUCCESS) {
     750                                goto failed;
    597751                        }
    598752                }
    599753        }
    600754
    601         return mod;
    602 }
     755        /* steal resulting message into supplied context */
     756        talloc_steal(mem_ctx, mod);
     757        *_msg_out = mod;
     758
     759        talloc_free(temp_ctx);
     760        return LDB_SUCCESS;
     761
     762failed:
     763        talloc_free(temp_ctx);
     764        return LDB_ERR_OPERATIONS_ERROR;
     765}
     766
    603767
    604768int ldb_msg_sanity_check(struct ldb_context *ldb,
    605769                         const struct ldb_message *msg)
    606770{
    607         int i, j;
     771        unsigned int i, j;
    608772
    609773        /* basic check on DN */
     
    643807{
    644808        const char **ret;
    645         int i;
     809        unsigned int i;
     810
    646811        for (i=0;attrs && attrs[i];i++) /* noop */ ;
    647812        ret = talloc_array(mem_ctx, const char *, i+1);
     
    664829{
    665830        const char **ret;
    666         int i;
     831        unsigned int i;
    667832        bool found = false;
     833
    668834        for (i=0;attrs && attrs[i];i++) {
    669835                if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
     
    692858int ldb_attr_in_list(const char * const *attrs, const char *attr)
    693859{
    694         int i;
     860        unsigned int i;
    695861        for (i=0;attrs && attrs[i];i++) {
    696862                if (ldb_attr_cmp(attrs[i], attr) == 0) {
     
    725891{
    726892        struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
     893        int ret;
     894
    727895        if (el == NULL) {
    728896                return LDB_SUCCESS;
    729897        }
    730         if (ldb_msg_add(msg, el, 0) != 0) {
    731                 return LDB_ERR_OPERATIONS_ERROR;
     898        ret = ldb_msg_add(msg, el, 0);
     899        if (ret != LDB_SUCCESS) {
     900                return ret;
    732901        }
    733902        return ldb_msg_rename_attr(msg, attr, replace);
     
    739908void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
    740909{
    741         int n = (el - msg->elements);
     910        ptrdiff_t n = (el - msg->elements);
    742911        if (n >= msg->num_elements) {
    743912                /* should we abort() here? */
     
    756925void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
    757926{
    758         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
    759         if (el) {
     927        struct ldb_message_element *el;
     928
     929        while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
    760930                ldb_msg_remove_element(msg, el);
    761931        }
     
    803973       
    804974        memset(&tm, 0, sizeof(tm));
    805         if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
     975        if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
    806976                   &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    807977                   &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
     
    812982       
    813983        return timegm(&tm);
     984}
     985
     986/*
     987  convert a LDAP GeneralizedTime string in ldb_val format to a
     988  time_t.
     989*/
     990int ldb_val_to_time(const struct ldb_val *v, time_t *t)
     991{
     992        struct tm tm;
     993
     994        if (v == NULL || !v->data || v->length < 17) {
     995                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     996        }
     997
     998        memset(&tm, 0, sizeof(tm));
     999
     1000        if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z",
     1001                   &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
     1002                   &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
     1003                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     1004        }
     1005        tm.tm_year -= 1900;
     1006        tm.tm_mon -= 1;
     1007
     1008        *t = timegm(&tm);
     1009
     1010        return LDB_SUCCESS;
    8141011}
    8151012
     
    8551052       
    8561053        memset(&tm, 0, sizeof(tm));
    857         if (sscanf(s, "%02u%02u%02u%02u%02u%02u",
     1054        if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
    8581055                   &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    8591056                   &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
     
    8741071void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
    8751072{
    876         int i;
     1073        unsigned int i;
    8771074
    8781075        for (i = 0; i < result->count; i++) {
     
    8851082}
    8861083
    887 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
     1084/*
     1085  checks for a string attribute. Returns "1" on match and otherwise "0".
     1086*/
     1087int ldb_msg_check_string_attribute(const struct ldb_message *msg,
     1088                                   const char *name, const char *value)
    8881089{
    8891090        struct ldb_message_element *el;
     
    8911092       
    8921093        el = ldb_msg_find_element(msg, name);
    893         if (el == NULL)
     1094        if (el == NULL) {
    8941095                return 0;
     1096        }
    8951097
    8961098        val.data = discard_const_p(uint8_t, value);
    8971099        val.length = strlen(value);
    8981100
    899         if (ldb_msg_find_val(el, &val))
     1101        if (ldb_msg_find_val(el, &val)) {
    9001102                return 1;
     1103        }
    9011104
    9021105        return 0;
    9031106}
     1107
  • trunk/server/source4/lib/ldb/common/ldb_parse.c

    r414 r745  
    4343#include "ldb_private.h"
    4444#include "system/locale.h"
     45
     46static int ldb_parse_hex2char(const char *x)
     47{
     48        if (isxdigit(x[0]) && isxdigit(x[1])) {
     49                const char h1 = x[0], h2 = x[1];
     50                int c = 0;
     51
     52                if (h1 >= 'a') c = h1 - (int)'a' + 10;
     53                else if (h1 >= 'A') c = h1 - (int)'A' + 10;
     54                else if (h1 >= '0') c = h1 - (int)'0';
     55                c = c << 4;
     56                if (h2 >= 'a') c += h2 - (int)'a' + 10;
     57                else if (h2 >= 'A') c += h2 - (int)'A' + 10;
     58                else if (h2 >= '0') c += h2 - (int)'0';
     59
     60                return c;
     61        }
     62
     63        return -1;
     64}
    4565
    4666/*
     
    6080   Used in LDAP filters.
    6181*/
    62 struct ldb_val ldb_binary_decode(void *mem_ctx, const char *str)
    63 {
    64         int i, j;
     82struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str)
     83{
     84        size_t i, j;
    6585        struct ldb_val ret;
    66         int slen = str?strlen(str):0;
     86        size_t slen = str?strlen(str):0;
    6787
    6888        ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1);
     
    7292        for (i=j=0;i<slen;i++) {
    7393                if (str[i] == '\\') {
    74                         unsigned c;
    75                         if (sscanf(&str[i+1], "%02X", &c) != 1) {
     94                        int c;
     95
     96                        c = ldb_parse_hex2char(&str[i+1]);
     97                        if (c == -1) {
    7698                                talloc_free(ret.data);
    7799                                memset(&ret, 0, sizeof(ret));
     
    95117   non-printable or '\' characters
    96118*/
    97 char *ldb_binary_encode(void *mem_ctx, struct ldb_val val)
    98 {
    99         int i;
     119char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val)
     120{
     121        size_t i;
    100122        char *ret;
    101         int len = val.length;
     123        size_t len = val.length;
    102124        unsigned char *buf = val.data;
    103125
     
    130152   in escaping user data in ldap filters.
    131153*/
    132 char *ldb_binary_encode_string(void *mem_ctx, const char *string)
     154char *ldb_binary_encode_string(TALLOC_CTX *mem_ctx, const char *string)
    133155{
    134156        struct ldb_val val;
     157        if (string == NULL) {
     158                return NULL;
     159        }
    135160        val.data = discard_const_p(uint8_t, string);
    136161        val.length = strlen(string);
     
    160185   chunks separated by wildcards that makes the value portion of the filter
    161186*/
    162 static struct ldb_val **ldb_wildcard_decode(void *mem_ctx, const char *string)
     187static struct ldb_val **ldb_wildcard_decode(TALLOC_CTX *mem_ctx, const char *string)
    163188{
    164189        struct ldb_val **ret = NULL;
    165         int val = 0;
     190        unsigned int val = 0;
    166191        char *wc, *str;
    167192
     
    200225}
    201226
    202 static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s);
     227static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s);
    203228
    204229
     
    254279}
    255280
    256 static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char **value, const char **s)
     281static enum ldb_parse_op ldb_parse_filtertype(TALLOC_CTX *mem_ctx, char **type, char **value, const char **s)
    257282{
    258283        enum ldb_parse_op filter = 0;
     
    352377  <simple> ::= <attributetype> <filtertype> <attributevalue>
    353378*/
    354 static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char **s)
     379static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *mem_ctx, const char **s)
    355380{
    356381        char *attr, *value;
     
    467492  <filterlist> ::= <filter> | <filter> <filterlist>
    468493*/
    469 static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, const char **s)
     494static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const char **s)
    470495{
    471496        struct ldb_parse_tree *ret, *next;
     
    535560  <not> ::= '!' <filter>
    536561*/
    537 static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char **s)
     562static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s)
    538563{
    539564        struct ldb_parse_tree *ret;
     
    567592  <filtercomp> ::= <and> | <or> | <not> | <simple>
    568593*/
    569 static struct ldb_parse_tree *ldb_parse_filtercomp(void *mem_ctx, const char **s)
     594static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const char **s)
    570595{
    571596        struct ldb_parse_tree *ret;
     
    604629  <filter> ::= '(' <filtercomp> ')'
    605630*/
    606 static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s)
     631static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s)
    607632{
    608633        struct ldb_parse_tree *ret;
     
    636661  expression ::= <simple> | <filter>
    637662*/
    638 struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s)
     663struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
    639664{
    640665        if (s == NULL || *s == 0) {
     
    655680  construct a ldap parse filter given a parse tree
    656681*/
    657 char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree)
     682char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, const struct ldb_parse_tree *tree)
    658683{
    659684        char *s, *s2, *ret;
    660         int i;
     685        unsigned int i;
    661686
    662687        if (tree == NULL) {
     
    774799
    775800/*
    776   replace any occurances of an attribute name in the parse tree with a
     801  replace any occurrences of an attribute name in the parse tree with a
    777802  new name
    778803*/
     
    781806                                 const char *replace)
    782807{
    783         int i;
     808        unsigned int i;
    784809        switch (tree->operation) {
    785810        case LDB_OP_AND:
     
    827852                                                   const struct ldb_parse_tree *ot)
    828853{
    829         int i;
     854        unsigned int i;
    830855        struct ldb_parse_tree *nt;
    831856
  • trunk/server/source4/lib/ldb/common/ldb_utf8.c

    r414 r745  
    5454  NOTE: does not handle UTF8
    5555*/
    56 char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n)
     56char *ldb_casefold_default(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n)
    5757{
    58         int i;
     58        size_t i;
    5959        char *ret = talloc_strndup(mem_ctx, s, n);
    6060        if (!s) {
     
    7373}
    7474
    75 char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s, size_t n)
     75char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n)
    7676{
    7777        return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s, n);
     
    8585int ldb_valid_attr_name(const char *s)
    8686{
    87         int i;
     87        size_t i;
    8888
    8989        if (!s || !s[0])
     
    110110}
    111111
    112 char *ldb_attr_casefold(void *mem_ctx, const char *s)
     112char *ldb_attr_casefold(TALLOC_CTX *mem_ctx, const char *s)
    113113{
    114         int i;
     114        size_t i;
    115115        char *ret = talloc_strdup(mem_ctx, s);
    116116        if (!ret) {
  • trunk/server/source4/lib/ldb/include/dlinklist.h

    r414 r745  
    22   Unix SMB/CIFS implementation.
    33   some simple double linked list macros
    4    Copyright (C) Andrew Tridgell 1998
     4
     5   Copyright (C) Andrew Tridgell 1998-2010
     6
     7     ** NOTE! The following LGPL license applies to the ldb
     8     ** library. This does NOT imply that all of Samba is released
     9     ** under the LGPL
    510   
    6    This program is free software; you can redistribute it and/or modify
    7    it under the terms of the GNU General Public License as published by
    8    the Free Software Foundation; either version 3 of the License, or
    9    (at your option) any later version.
    10    
    11    This program is distributed in the hope that it will be useful,
     11   This library is free software; you can redistribute it and/or
     12   modify it under the terms of the GNU Lesser General Public
     13   License as published by the Free Software Foundation; either
     14   version 3 of the License, or (at your option) any later version.
     15
     16   This library is distributed in the hope that it will be useful,
    1217   but WITHOUT ANY WARRANTY; without even the implied warranty of
    13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14    GNU General Public License for more details.
    15    
    16    You should have received a copy of the GNU General Public License
    17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     19   Lesser General Public License for more details.
     20
     21   You should have received a copy of the GNU Lesser General Public
     22   License along with this library; if not, see <http://www.gnu.org/licenses/>.
    1823*/
    1924
     
    2429#define _DLINKLIST_H
    2530
     31/*
     32  February 2010 - changed list format to have a prev pointer from the
     33  list head. This makes DLIST_ADD_END() O(1) even though we only have
     34  one list pointer.
    2635
    27 /* hook into the front of the list */
     36  The scheme is as follows:
     37
     38     1) with no entries in the list:
     39          list_head == NULL
     40
     41     2) with 1 entry in the list:
     42          list_head->next == NULL
     43          list_head->prev == list_head
     44
     45     3) with 2 entries in the list:
     46          list_head->next == element2
     47          list_head->prev == element2
     48          element2->prev == list_head
     49          element2->next == NULL
     50
     51     4) with N entries in the list:
     52          list_head->next == element2
     53          list_head->prev == elementN
     54          elementN->prev == element{N-1}
     55          elementN->next == NULL
     56
     57  This allows us to find the tail of the list by using
     58  list_head->prev, which means we can add to the end of the list in
     59  O(1) time
     60
     61
     62  Note that the 'type' arguments below are no longer needed, but
     63  are kept for now to prevent an incompatible argument change
     64 */
     65
     66
     67/*
     68   add an element at the front of a list
     69*/
    2870#define DLIST_ADD(list, p) \
    2971do { \
    3072        if (!(list)) { \
    31                 (list) = (p); \
    32                 (p)->next = (p)->prev = NULL; \
     73                (p)->prev = (list) = (p); \
     74                (p)->next = NULL; \
    3375        } else { \
     76                (p)->prev = (list)->prev; \
    3477                (list)->prev = (p); \
    3578                (p)->next = (list); \
    36                 (p)->prev = NULL; \
    3779                (list) = (p); \
    38         }\
     80        } \
    3981} while (0)
    4082
    41 /* remove an element from a list - element doesn't have to be in list. */
     83/*
     84   remove an element from a list
     85   Note that the element doesn't have to be in the list. If it
     86   isn't then this is a no-op
     87*/
    4288#define DLIST_REMOVE(list, p) \
    4389do { \
    4490        if ((p) == (list)) { \
     91                if ((p)->next) (p)->next->prev = (p)->prev; \
    4592                (list) = (p)->next; \
    46                 if (list) (list)->prev = NULL; \
     93        } else if ((list) && (p) == (list)->prev) {     \
     94                (p)->prev->next = NULL; \
     95                (list)->prev = (p)->prev; \
    4796        } else { \
    4897                if ((p)->prev) (p)->prev->next = (p)->next; \
    4998                if ((p)->next) (p)->next->prev = (p)->prev; \
    5099        } \
    51         if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
     100        if ((p) != (list)) (p)->next = (p)->prev = NULL;        \
    52101} while (0)
    53102
    54 /* promote an element to the top of the list */
    55 #define DLIST_PROMOTE(list, p) \
     103/*
     104   find the head of the list given any element in it.
     105   Note that this costs O(N), so you should avoid this macro
     106   if at all possible!
     107*/
     108#define DLIST_HEAD(p, result_head) \
    56109do { \
    57           DLIST_REMOVE(list, p); \
    58           DLIST_ADD(list, p); \
    59 } while (0)
     110       (result_head) = (p); \
     111       while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
     112} while(0)
    60113
    61 /* hook into the end of the list - needs the entry type */
    62 #define DLIST_ADD_END(list, p, type) \
    63 do { \
    64                 if (!(list)) { \
    65                         (list) = (p); \
    66                         (p)->next = (p)->prev = NULL; \
    67                 } else { \
    68                         type tmp; \
    69                         for (tmp = (list); tmp->next; tmp = tmp->next) ; \
    70                         tmp->next = (p); \
    71                         (p)->next = NULL; \
    72                         (p)->prev = tmp; \
    73                 } \
    74 } while (0)
     114/* return the last element in the list */
     115#define DLIST_TAIL(list) ((list)?(list)->prev:NULL)
     116
     117/* return the previous element in the list. */
     118#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL)
    75119
    76120/* insert 'p' after the given element 'el' in a list. If el is NULL then
     
    81125                DLIST_ADD(list, p); \
    82126        } else { \
    83                 p->prev = el; \
    84                 p->next = el->next; \
    85                 el->next = p; \
    86                 if (p->next) p->next->prev = p; \
     127                (p)->prev = (el);   \
     128                (p)->next = (el)->next;         \
     129                (el)->next = (p);               \
     130                if ((p)->next) (p)->next->prev = (p);   \
     131                if ((list)->prev == (el)) (list)->prev = (p); \
    87132        }\
    88133} while (0)
    89134
    90 /* demote an element to the end of the list, needs the entry type */
    91 #define DLIST_DEMOTE(list, p, type) \
     135
     136/*
     137   add to the end of a list.
     138   Note that 'type' is ignored
     139*/
     140#define DLIST_ADD_END(list, p, type)                    \
    92141do { \
    93                 DLIST_REMOVE(list, p); \
    94                 DLIST_ADD_END(list, p, type); \
     142        if (!(list)) { \
     143                DLIST_ADD(list, p); \
     144        } else { \
     145                DLIST_ADD_AFTER(list, p, (list)->prev); \
     146        } \
    95147} while (0)
    96148
    97 /* concatenate two lists - putting all elements of the 2nd list at the
    98    end of the first list */
    99 #define DLIST_CONCATENATE(list1, list2, type) \
     149/* promote an element to the from of a list */
     150#define DLIST_PROMOTE(list, p) \
    100151do { \
    101                 if (!(list1)) { \
    102                         (list1) = (list2); \
    103                 } else { \
    104                         type tmp; \
    105                         for (tmp = (list1); tmp->next; tmp = tmp->next) ; \
    106                         tmp->next = (list2); \
    107                         if (list2) { \
    108                                 (list2)->prev = tmp;    \
    109                         } \
     152          DLIST_REMOVE(list, p); \
     153          DLIST_ADD(list, p); \
     154} while (0)
     155
     156/*
     157   demote an element to the end of a list.
     158   Note that 'type' is ignored
     159*/
     160#define DLIST_DEMOTE(list, p, type)                     \
     161do { \
     162        DLIST_REMOVE(list, p); \
     163        DLIST_ADD_END(list, p, NULL);           \
     164} while (0)
     165
     166/*
     167   concatenate two lists - putting all elements of the 2nd list at the
     168   end of the first list.
     169   Note that 'type' is ignored
     170*/
     171#define DLIST_CONCATENATE(list1, list2, type)   \
     172do { \
     173        if (!(list1)) { \
     174                (list1) = (list2); \
     175        } else { \
     176                (list1)->prev->next = (list2); \
     177                if (list2) { \
     178                        void *_tmplist = (void *)(list1)->prev; \
     179                        (list1)->prev = (list2)->prev; \
     180                        (list2)->prev = _tmplist; \
    110181                } \
     182        } \
    111183} while (0)
    112184
  • trunk/server/source4/lib/ldb/include/ldb.h

    r414 r745  
    4848
    4949#include <stdbool.h>
    50 #include "talloc.h"
    51 #include "tevent.h"
    52 #include "ldb_errors.h"
     50#include <talloc.h>
     51#include <tevent.h>
     52#include <ldb_version.h>
     53#include <ldb_errors.h>
    5354
    5455/*
     
    8687#ifndef PRINTF_ATTRIBUTE
    8788#define PRINTF_ATTRIBUTE(a,b)
     89#endif
     90
     91#ifndef _DEPRECATED_
     92#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
     93#define _DEPRECATED_ __attribute__ ((deprecated))
     94#else
     95#define _DEPRECATED_
     96#endif
    8897#endif
    8998/*! \endcond */
     
    103112
    104113/**
     114  use this to extract the mod type from the operation
     115 */
     116#define LDB_FLAG_MOD_TYPE(flags) ((flags) & LDB_FLAG_MOD_MASK)
     117
     118/**
    105119   Flag value used in ldap_modify() to indicate that attributes are
    106120   being added.
     
    125139*/
    126140#define LDB_FLAG_MOD_DELETE  3
     141
     142/**
     143    flag bits on an element usable only by the internal implementation
     144*/
     145#define LDB_FLAG_INTERNAL_MASK 0xFFFFFFF0
    127146
    128147/**
     
    297316
    298317struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s);
    299 char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, struct ldb_parse_tree *tree);
     318char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, const struct ldb_parse_tree *tree);
    300319
    301320/**
     
    336355typedef int (*ldb_attr_handler_t)(struct ldb_context *, TALLOC_CTX *mem_ctx, const struct ldb_val *, struct ldb_val *);
    337356typedef int (*ldb_attr_comparison_t)(struct ldb_context *, TALLOC_CTX *mem_ctx, const struct ldb_val *, const struct ldb_val *);
     357struct ldb_schema_attribute;
     358typedef int (*ldb_attr_operator_t)(struct ldb_context *, enum ldb_parse_op operation,
     359                                   const struct ldb_schema_attribute *a,
     360                                   const struct ldb_val *, const struct ldb_val *, bool *matched);
    338361
    339362/*
     
    353376        ldb_attr_handler_t canonicalise_fn;
    354377        ldb_attr_comparison_t comparison_fn;
     378        ldb_attr_operator_t operator_fn;
    355379};
    356380
     
    457481typedef int (*ldb_qsort_cmp_fn_t) (void *v1, void *v2, void *opaque);
    458482
     483/* Individual controls */
     484
     485/**
     486  OID for getting and manipulating attributes from the ldb
     487  without interception in the operational module.
     488  It can be used to access attribute that used to be stored in the sam
     489  and that are now calculated.
     490*/
     491#define LDB_CONTROL_BYPASS_OPERATIONAL_OID "1.3.6.1.4.1.7165.4.3.13"
     492#define LDB_CONTROL_BYPASS_OPERATIONAL_NAME "bypassoperational"
     493
     494/**
     495  OID for recalculate SD control. This control force the
     496  dsdb code to recalculate the SD of the object as if the
     497  object was just created.
     498
     499*/
     500#define LDB_CONTROL_RECALCULATE_SD_OID "1.3.6.1.4.1.7165.4.3.5"
     501#define LDB_CONTROL_RECALCULATE_SD_NAME "recalculate_sd"
     502
     503/**
     504   REVEAL_INTERNALS is used to reveal internal attributes and DN
     505   components which are not normally shown to the user
     506*/
     507#define LDB_CONTROL_REVEAL_INTERNALS "1.3.6.1.4.1.7165.4.3.6"
     508#define LDB_CONTROL_REVEAL_INTERNALS_NAME       "reveal_internals"
     509
     510/**
     511   LDB_CONTROL_AS_SYSTEM is used to skip access checks on operations
     512   that are performed by the system, but with a user's credentials, e.g.
     513   updating prefix map
     514*/
     515#define LDB_CONTROL_AS_SYSTEM_OID "1.3.6.1.4.1.7165.4.3.7"
     516
     517/**
     518   LDB_CONTROL_PROVISION_OID is used to skip some constraint checks. It's is
     519   mainly thought to be used for the provisioning.
     520*/
     521#define LDB_CONTROL_PROVISION_OID "1.3.6.1.4.1.7165.4.3.16"
     522#define LDB_CONTROL_PROVISION_NAME      "provision"
     523
     524/* AD controls */
     525
    459526/**
    460527   OID for the paged results control. This control is included in the
     
    466533*/
    467534#define LDB_CONTROL_PAGED_RESULTS_OID   "1.2.840.113556.1.4.319"
     535#define LDB_CONTROL_PAGED_RESULTS_NAME  "paged_result"
    468536
    469537/**
     
    473541*/
    474542#define LDB_CONTROL_SD_FLAGS_OID        "1.2.840.113556.1.4.801"
     543#define LDB_CONTROL_SD_FLAGS_NAME       "sd_flags"
    475544
    476545/**
     
    480549*/
    481550#define LDB_CONTROL_DOMAIN_SCOPE_OID    "1.2.840.113556.1.4.1339"
     551#define LDB_CONTROL_DOMAIN_SCOPE_NAME   "domain_scope"
    482552
    483553/**
     
    487557*/
    488558#define LDB_CONTROL_SEARCH_OPTIONS_OID  "1.2.840.113556.1.4.1340"
     559#define LDB_CONTROL_SEARCH_OPTIONS_NAME "search_options"
    489560
    490561/**
     
    494565*/
    495566#define LDB_CONTROL_NOTIFICATION_OID    "1.2.840.113556.1.4.528"
     567#define LDB_CONTROL_NOTIFICATION_NAME   "notification"
     568
     569/**
     570   OID for performing subtree deletes
     571
     572   \sa <a href="http://msdn.microsoft.com/en-us/library/aa366991(v=VS.85).aspx">Microsoft documentation of this OID</a>
     573*/
     574#define LDB_CONTROL_TREE_DELETE_OID     "1.2.840.113556.1.4.805"
     575#define LDB_CONTROL_TREE_DELETE_NAME    "tree_delete"
    496576
    497577/**
     
    501581*/
    502582#define LDB_CONTROL_SHOW_DELETED_OID    "1.2.840.113556.1.4.417"
     583#define LDB_CONTROL_SHOW_DELETED_NAME   "show_deleted"
    503584
    504585/**
     
    508589*/
    509590#define LDB_CONTROL_SHOW_RECYCLED_OID         "1.2.840.113556.1.4.2064"
     591#define LDB_CONTROL_SHOW_RECYCLED_NAME  "show_recycled"
    510592
    511593/**
     
    515597*/
    516598#define LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID "1.2.840.113556.1.4.2065"
     599#define LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME  "show_deactivated_link"
    517600
    518601/**
     
    522605*/
    523606#define LDB_CONTROL_EXTENDED_DN_OID     "1.2.840.113556.1.4.529"
     607#define LDB_CONTROL_EXTENDED_DN_NAME    "extended_dn"
    524608
    525609/**
     
    536620*/
    537621#define LDB_CONTROL_SERVER_SORT_OID     "1.2.840.113556.1.4.473"
     622#define LDB_CONTROL_SERVER_SORT_NAME    "server_sort"
    538623
    539624/**
     
    547632*/
    548633#define LDB_CONTROL_SORT_RESP_OID       "1.2.840.113556.1.4.474"
     634#define LDB_CONTROL_SORT_RESP_NAME      "server_sort_resp"
    549635
    550636/**
     
    555641*/
    556642#define LDB_CONTROL_ASQ_OID             "1.2.840.113556.1.4.1504"
     643#define LDB_CONTROL_ASQ_NAME    "asq"
    557644
    558645/**
     
    563650*/
    564651#define LDB_CONTROL_DIRSYNC_OID         "1.2.840.113556.1.4.841"
     652#define LDB_CONTROL_DIRSYNC_NAME        "dirsync"
    565653
    566654
     
    572660*/
    573661#define LDB_CONTROL_VLV_REQ_OID         "2.16.840.1.113730.3.4.9"
     662#define LDB_CONTROL_VLV_REQ_NAME        "vlv"
    574663
    575664/**
     
    580669*/
    581670#define LDB_CONTROL_VLV_RESP_OID        "2.16.840.1.113730.3.4.10"
     671#define LDB_CONTROL_VLV_RESP_NAME       "vlv_resp"
    582672
    583673/**
     
    588678*/
    589679#define LDB_CONTROL_PERMISSIVE_MODIFY_OID       "1.2.840.113556.1.4.1413"
     680#define LDB_CONTROL_PERMISSIVE_MODIFY_NAME      "permissive_modify"
     681
     682/**
     683    OID to allow the server to be more 'fast and loose' with the data being added. 
     684
     685    \sa <a href="http://msdn.microsoft.com/en-us/library/aa366982(v=VS.85).aspx">Microsoft documentation of this OID</a>
     686*/
     687#define LDB_CONTROL_SERVER_LAZY_COMMIT   "1.2.840.113556.1.4.619"
     688
     689/**
     690   Control for RODC join -see [MS-ADTS] section 3.1.1.3.4.1.23
     691
     692   \sa <a href="">Microsoft documentation of this OID</a>
     693*/
     694#define LDB_CONTROL_RODC_DCPROMO_OID "1.2.840.113556.1.4.1341"
     695#define LDB_CONTROL_RODC_DCPROMO_NAME   "rodc_join"
     696
     697/* Other standardised controls */
     698
     699/**
     700   OID for the allowing client to request temporary relaxed
     701   enforcement of constraints of the x.500 model.
     702
     703   Mainly used for the OpenLDAP backend.
     704
     705   \sa <a href="http://opends.dev.java.net/public/standards/draft-zeilenga-ldap-managedit.txt">draft managedit</a>.
     706*/
     707#define LDB_CONTROL_RELAX_OID "1.3.6.1.4.1.4203.666.5.12"
     708#define LDB_CONTROL_RELAX_NAME  "relax"
     709
     710/* Extended operations */
     711
     712/**
     713   OID for LDAP Extended Operation SEQUENCE_NUMBER
     714
     715   This extended operation is used to retrieve the extended sequence number.
     716*/
     717#define LDB_EXTENDED_SEQUENCE_NUMBER    "1.3.6.1.4.1.7165.4.4.3"
     718
     719/**
     720   OID for LDAP Extended Operation PASSWORD_CHANGE.
     721
     722   This Extended operation is used to allow user password changes by the user
     723   itself.
     724*/
     725#define LDB_EXTENDED_PASSWORD_CHANGE_OID        "1.3.6.1.4.1.4203.1.11.1"
     726
     727
     728/**
     729   OID for LDAP Extended Operation FAST_BIND
     730
     731   This Extended operations is used to perform a fast bind.
     732*/
     733#define LDB_EXTENDED_FAST_BIND_OID      "1.2.840.113556.1.4.1781"
    590734
    591735/**
    592736   OID for LDAP Extended Operation START_TLS.
    593737
    594    This Extended operation is used to start a new TLS
    595    channel on top of a clear text channel.
     738   This Extended operation is used to start a new TLS channel on top of a clear
     739   text channel.
    596740*/
    597741#define LDB_EXTENDED_START_TLS_OID      "1.3.6.1.4.1.1466.20037"
    598742
    599743/**
     744   OID for LDAP Extended Operation DYNAMIC_REFRESH.
     745
     746   This Extended operation is used to create and maintain objects which exist
     747   only a specific time, e.g. when a certain client or a certain person is
     748   logged in. Data refreshes have to be periodically sent in a specific
     749   interval. Otherwise the entry is going to be removed.
    600750*/
    601751#define LDB_EXTENDED_DYNAMIC_OID        "1.3.6.1.4.1.1466.101.119.1"
    602 
    603 /**
    604 */
    605 #define LDB_EXTENDED_FAST_BIND_OID      "1.2.840.113556.1.4.1781"
    606752
    607753struct ldb_sd_flags_control {
     
    736882};
    737883
    738 #define LDB_EXTENDED_SEQUENCE_NUMBER    "1.3.6.1.4.1.7165.4.4.3"
    739 
    740884enum ldb_sequence_type {
    741885        LDB_SEQ_HIGHEST_SEQ,
     
    9641108int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares);
    9651109
     1110int ldb_modify_default_callback(struct ldb_request *req, struct ldb_reply *ares);
    9661111
    9671112/**
     
    11181263
    11191264/**
     1265  replace a ldb_control in a ldb_request
     1266
     1267  \param req the request struct where to add the control
     1268  \param oid the object identifier of the control as string
     1269  \param critical whether the control should be critical or not
     1270  \param data a talloc pointer to the control specific data
     1271
     1272  \return result code (LDB_SUCCESS on success, or a failure code)
     1273*/
     1274int ldb_request_replace_control(struct ldb_request *req, const char *oid, bool critical, void *data);
     1275
     1276/**
    11201277   check if a control with the specified "oid" exist and return it
    11211278  \param req the request struct where to add the control
     
    13091466int ldb_transaction_cancel(struct ldb_context *ldb);
    13101467
     1468/*
     1469  cancel a transaction with no error if no transaction is pending
     1470  used when we fork() to clear any parent transactions
     1471*/
     1472int ldb_transaction_cancel_noerr(struct ldb_context *ldb);
     1473
    13111474
    13121475/**
     
    15511714  \param mode Style of extended DN to return (0 is HEX representation of binary form, 1 is a string form)
    15521715*/
    1553 char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode);
     1716char *ldb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int mode);
    15541717const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name);
    15551718int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val);
    1556 
     1719void ldb_dn_extended_filter(struct ldb_dn *dn, const char * const *accept_list);
    15571720void ldb_dn_remove_extended_components(struct ldb_dn *dn);
    15581721bool ldb_dn_has_extended(struct ldb_dn *dn);
     
    15911754*/
    15921755
    1593 struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn);
     1756struct ldb_dn *ldb_dn_from_ldb_val(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn);
    15941757
    15951758/**
     
    16201783char *ldb_dn_canonical_ex_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
    16211784int ldb_dn_get_comp_num(struct ldb_dn *dn);
     1785int ldb_dn_get_extended_comp_num(struct ldb_dn *dn);
    16221786const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num);
    16231787const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num);
     
    16301794bool ldb_dn_check_special(struct ldb_dn *dn, const char *check);
    16311795bool ldb_dn_is_null(struct ldb_dn *dn);
     1796int ldb_dn_update_components(struct ldb_dn *dn, const struct ldb_dn *ref_dn);
    16321797
    16331798
     
    17131878int ldb_msg_add_string(struct ldb_message *msg,
    17141879                       const char *attr_name, const char *str);
     1880int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
     1881                              struct ldb_dn *dn);
    17151882int ldb_msg_add_fmt(struct ldb_message *msg,
    17161883                    const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
     
    17661933                                 const struct ldb_message *msg);
    17671934
     1935/*
     1936 * ldb_msg_canonicalize() is now depreciated
     1937 * Please use ldb_msg_normalize() instead
     1938 *
     1939 * NOTE: Returned ldb_message object is allocated
     1940 * into *ldb's context. Callers are recommended
     1941 * to steal the returned object into a TALLOC_CTX
     1942 * with short lifetime.
     1943 */
    17681944struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
    1769                                          const struct ldb_message *msg);
    1770 
    1771 
     1945                                         const struct ldb_message *msg) _DEPRECATED_;
     1946
     1947int ldb_msg_normalize(struct ldb_context *ldb,
     1948                      TALLOC_CTX *mem_ctx,
     1949                      const struct ldb_message *msg,
     1950                      struct ldb_message **_msg_out);
     1951
     1952
     1953/*
     1954 * ldb_msg_diff() is now depreciated
     1955 * Please use ldb_msg_difference() instead
     1956 *
     1957 * NOTE: Returned ldb_message object is allocated
     1958 * into *ldb's context. Callers are recommended
     1959 * to steal the returned object into a TALLOC_CTX
     1960 * with short lifetime.
     1961 */
    17721962struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
    17731963                                 struct ldb_message *msg1,
    1774                                  struct ldb_message *msg2);
    1775 
     1964                                 struct ldb_message *msg2) _DEPRECATED_;
     1965
     1966/**
     1967 * return a ldb_message representing the differences between msg1 and msg2.
     1968 * If you then use this in a ldb_modify() call,
     1969 * it can be used to save edits to a message
     1970 *
     1971 * Result message is constructed as follows:
     1972 * - LDB_FLAG_MOD_ADD     - elements found only in msg2
     1973 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have
     1974 *                          different value in msg1
     1975 *                          Value for msg2 element is used
     1976 * - LDB_FLAG_MOD_DELETE  - elements found only in msg2
     1977 *
     1978 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
     1979 */
     1980int ldb_msg_difference(struct ldb_context *ldb,
     1981                       TALLOC_CTX *mem_ctx,
     1982                       struct ldb_message *msg1,
     1983                       struct ldb_message *msg2,
     1984                       struct ldb_message **_msg_out);
     1985
     1986/**
     1987   Tries to find a certain string attribute in a message
     1988
     1989   \param msg the message to check
     1990   \param name attribute name
     1991   \param value attribute value
     1992
     1993   \return 1 on match and 0 otherwise.
     1994*/
    17761995int ldb_msg_check_string_attribute(const struct ldb_message *msg,
    17771996                                   const char *name,
     
    18802099
    18812100/**
     2101  convert a LDAP GeneralizedTime string in ldb_val format to a
     2102  time_t.
     2103*/
     2104int ldb_val_to_time(const struct ldb_val *v, time_t *t);
     2105
     2106/**
    18822107   Convert a time structure to a string
    18832108
     
    19082133void ldb_qsort (void *const pbase, size_t total_elems, size_t size, void *opaque, ldb_qsort_cmp_fn_t cmp);
    19092134
    1910 
     2135#ifndef discard_const
     2136#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
     2137#endif
     2138
     2139/*
     2140  a wrapper around ldb_qsort() that ensures the comparison function is
     2141  type safe. This will produce a compilation warning if the types
     2142  don't match
     2143 */
     2144#define LDB_TYPESAFE_QSORT(base, numel, opaque, comparison)     \
     2145do { \
     2146        if (numel > 1) { \
     2147                ldb_qsort(base, numel, sizeof((base)[0]), discard_const(opaque), (ldb_qsort_cmp_fn_t)comparison); \
     2148                comparison(&((base)[0]), &((base)[1]), opaque);         \
     2149        } \
     2150} while (0)
     2151
     2152/* allow ldb to also call TYPESAFE_QSORT() */
     2153#ifndef TYPESAFE_QSORT
     2154#define TYPESAFE_QSORT(base, numel, comparison) \
     2155do { \
     2156        if (numel > 1) { \
     2157                qsort(base, numel, sizeof((base)[0]), (int (*)(const void *, const void *))comparison); \
     2158                comparison(&((base)[0]), &((base)[1])); \
     2159        } \
     2160} while (0)
     2161#endif
     2162
     2163
     2164
     2165/**
     2166   Convert a control into its string representation.
     2167   
     2168   \param mem_ctx TALLOC context to return result on, and to allocate error_string on
     2169   \param control A struct ldb_control to convert
     2170
     2171   \return string representation of the control
     2172*/
     2173char* ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *control);
     2174/**
     2175   Convert a string representing a control into a ldb_control structure
     2176   
     2177   \param ldb LDB context
     2178   \param mem_ctx TALLOC context to return result on, and to allocate error_string on
     2179   \param control_strings A string-formatted control
     2180
     2181   \return a ldb_control element
     2182*/
     2183struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings);
    19112184/**
    19122185   Convert an array of string represention of a control into an array of ldb_control structures
     
    19292202
    19302203
     2204struct ldb_dn *ldb_dn_binary_from_ldb_val(TALLOC_CTX *mem_ctx,
     2205                                          struct ldb_context *ldb,
     2206                                          const struct ldb_val *strdn);
     2207
     2208int ldb_dn_get_binary(struct ldb_dn *dn, struct ldb_val *val);
     2209int ldb_dn_set_binary(struct ldb_dn *dn, struct ldb_val *val);
     2210
     2211/* debugging functions for ldb requests */
     2212void ldb_req_set_location(struct ldb_request *req, const char *location);
     2213const char *ldb_req_location(struct ldb_request *req);
     2214
     2215/* set the location marker on a request handle - used for debugging */
     2216#define LDB_REQ_SET_LOCATION(req) ldb_req_set_location(req, __location__)
     2217
     2218/*
     2219  minimise a DN. The caller must pass in a validated DN.
     2220
     2221  If the DN has an extended component then only the first extended
     2222  component is kept, the DN string is stripped.
     2223
     2224  The existing dn is modified
     2225 */
     2226bool ldb_dn_minimise(struct ldb_dn *dn);
     2227
    19312228#endif
  • trunk/server/source4/lib/ldb/include/ldb_errors.h

    r414 r745  
    198198
    199199/**
    200    The function referred to an alias which points to a non-existant
     200   The function referred to an alias which points to a non-existent
    201201   object in the database.
    202202*/
  • trunk/server/source4/lib/ldb/include/ldb_handlers.h

    r414 r745  
    3636int ldb_comparison_binary(      struct ldb_context *ldb, void *mem_ctx,
    3737                                const struct ldb_val *v1, const struct ldb_val *v2);
    38 int db_handler_fold(            struct ldb_context *ldb, void *mem_ctx,
    39                                 const struct ldb_val *in, struct ldb_val *out);
    4038int ldb_comparison_fold(        struct ldb_context *ldb, void *mem_ctx,
    4139                                const struct ldb_val *v1, const struct ldb_val *v2);
  • trunk/server/source4/lib/ldb/include/ldb_module.h

    r414 r745  
    3434#define _LDB_MODULE_H_
    3535
    36 #include "ldb.h"
     36#include <ldb.h>
    3737
    3838struct ldb_context;
    3939struct ldb_module;
     40
     41/**
     42   internal flag bits on message elements. Must be within LDB_FLAG_INTERNAL_MASK
     43 */
     44#define LDB_FLAG_INTERNAL_DISABLE_VALIDATION 0x10
     45
     46/* disable any single value checking on this attribute */
     47#define LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK 0x20
     48
     49/* attribute has failed access check and must not be exposed */
     50#define LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE 0x40
     51
     52/* force single value checking on this attribute */
     53#define LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK 0x80
     54
    4055
    4156/*
     
    6883void ldb_debug_end(struct ldb_context *ldb, enum ldb_debug_level level);
    6984
    70 #define ldb_oom(ldb) ldb_debug_set(ldb, LDB_DEBUG_FATAL, "ldb out of memory at %s:%d\n", __FILE__, __LINE__)
     85#define ldb_error(ldb, ecode, reason) ldb_error_at(ldb, ecode, reason, __FILE__, __LINE__)
     86
     87#define ldb_oom(ldb) ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "ldb out of memory")
     88#define ldb_module_oom(module) ldb_oom(ldb_module_get_ctx(module))
     89#define ldb_operr(ldb) ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "operations error")
    7190
    7291/* The following definitions come from lib/ldb/common/ldb.c  */
     
    99118                                               void *private_data);
    100119
     120/* A useful function to build comparison functions with */
     121int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx,
     122                       ldb_attr_handler_t canonicalise_fn,
     123                       const struct ldb_val *v1,
     124                       const struct ldb_val *v2);
     125
    101126/* The following definitions come from lib/ldb/common/ldb_controls.c  */
    102 struct ldb_control *get_control_from_list(struct ldb_control **controls, const char *oid);
    103 int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver);
    104 int check_critical_controls(struct ldb_control **controls);
     127int ldb_save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver);
     128/* Returns a list of controls, except the one specified.  Included
     129 * controls become a child of returned list if they were children of
     130 * controls_in */
     131struct ldb_control **ldb_controls_except_specified(struct ldb_control **controls_in,
     132                                               TALLOC_CTX *mem_ctx,
     133                                               struct ldb_control *exclude);
     134int ldb_check_critical_controls(struct ldb_control **controls);
    105135
    106136/* The following definitions come from lib/ldb/common/ldb_ldif.c  */
     
    114144                  enum ldb_scope scope);
    115145
     146int ldb_match_msg_error(struct ldb_context *ldb,
     147                        const struct ldb_message *msg,
     148                        const struct ldb_parse_tree *tree,
     149                        struct ldb_dn *base,
     150                        enum ldb_scope scope,
     151                        bool *matched);
     152
     153int ldb_match_msg_objectclass(const struct ldb_message *msg,
     154                              const char *objectclass);
     155
    116156/* The following definitions come from lib/ldb/common/ldb_modules.c  */
    117157
     
    125165void *ldb_module_get_private(struct ldb_module *module);
    126166void ldb_module_set_private(struct ldb_module *module, void *private_data);
     167const struct ldb_module_ops *ldb_module_get_ops(struct ldb_module *module);
    127168
    128169int ldb_next_request(struct ldb_module *module, struct ldb_request *request);
     
    136177void ldb_asprintf_errstring(struct ldb_context *ldb, const char *format, ...) PRINTF_ATTRIBUTE(2,3);
    137178void ldb_reset_err_string(struct ldb_context *ldb);
     179int ldb_error_at(struct ldb_context *ldb, int ecode, const char *reason, const char *file, int line);
    138180
    139181const char *ldb_default_modules_dir(void);
     
    152194const char *ldb_default_modules_dir(void);
    153195
    154 int ldb_register_backend(const char *url_prefix, ldb_connect_fn);
     196int ldb_register_backend(const char *url_prefix, ldb_connect_fn, bool);
    155197
    156198struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb);
     
    171213
    172214void ldb_set_default_dns(struct ldb_context *ldb);
     215/**
     216  Add a ldb_control to a ldb_reply
     217
     218  \param ares the reply struct where to add the control
     219  \param oid the object identifier of the control as string
     220  \param critical whether the control should be critical or not
     221  \param data a talloc pointer to the control specific data
     222
     223  \return result code (LDB_SUCCESS on success, or a failure code)
     224*/
     225int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data);
     226
     227/**
     228  mark a request as untrusted. This tells the rootdse module to remove
     229  unregistered controls
     230 */
     231void ldb_req_mark_untrusted(struct ldb_request *req);
     232
     233/**
     234  mark a request as trusted.
     235 */
     236void ldb_req_mark_trusted(struct ldb_request *req);
     237
     238/**
     239   return true is a request is untrusted
     240 */
     241bool ldb_req_is_untrusted(struct ldb_request *req);
     242
     243/* load all modules from the given directory */
     244int ldb_modules_load(const char *modules_path, const char *version);
     245
     246/* init functions prototype */
     247typedef int (*ldb_module_init_fn)(const char *);
     248
     249/*
     250  general ldb hook function
     251 */
     252enum ldb_module_hook_type { LDB_MODULE_HOOK_CMDLINE_OPTIONS     = 1,
     253                            LDB_MODULE_HOOK_CMDLINE_PRECONNECT  = 2,
     254                            LDB_MODULE_HOOK_CMDLINE_POSTCONNECT = 3 };
     255
     256typedef int (*ldb_hook_fn)(struct ldb_context *, enum ldb_module_hook_type );
     257
     258/*
     259  register a ldb hook function
     260 */
     261int ldb_register_hook(ldb_hook_fn hook_fn);
     262
     263/*
     264  call ldb hooks of a given type
     265 */
     266int ldb_modules_hook(struct ldb_context *ldb, enum ldb_module_hook_type t);
     267
     268#define LDB_MODULE_CHECK_VERSION(version) do { \
     269 if (strcmp(version, LDB_VERSION) != 0) { \
     270        fprintf(stderr, "ldb: module version mismatch in %s : ldb_version=%s module_version=%s\n", \
     271                        __FILE__, version, LDB_VERSION); \
     272        return LDB_ERR_UNAVAILABLE; \
     273 }} while (0)
     274
     275
     276/*
     277  return a string representation of the calling chain for the given
     278  ldb request
     279 */
     280char *ldb_module_call_chain(struct ldb_request *req, TALLOC_CTX *mem_ctx);
     281
     282/*
     283  return the next module in the chain
     284 */
     285struct ldb_module *ldb_module_next(struct ldb_module *module);
     286
     287/*
     288  set the next module in the module chain
     289 */
     290void ldb_module_set_next(struct ldb_module *module, struct ldb_module *next);
     291
     292/*
     293  load a list of modules
     294 */
     295int ldb_module_load_list(struct ldb_context *ldb, const char **module_list,
     296                         struct ldb_module *backend, struct ldb_module **out);
     297
     298/*
     299  get the popt_options pointer in the ldb structure. This allows a ldb
     300  module to change the command line parsing
     301 */
     302struct poptOption **ldb_module_popt_options(struct ldb_context *ldb);
     303
     304/* modules are called in inverse order on the stack.
     305   Lets place them as an admin would think the right order is.
     306   Modules order is important */
     307const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *string);
     308
     309/*
     310  return the current ldb flags LDB_FLG_*
     311 */
     312uint32_t ldb_module_flags(struct ldb_context *ldb);
     313
     314int ldb_module_connect_backend(struct ldb_context *ldb,
     315                               const char *url,
     316                               const char *options[],
     317                               struct ldb_module **backend_module);
     318
     319/*
     320  initialise a chain of modules
     321 */
     322int ldb_module_init_chain(struct ldb_context *ldb, struct ldb_module *module);
     323
     324/*
     325 * prototype for the init function defined by dynamically loaded modules
     326 */
     327int ldb_init_module(const char *version);
     328
    173329
    174330#endif
  • trunk/server/source4/lib/ldb/include/ldb_private.h

    r414 r745  
    3838#define _LDB_PRIVATE_H_ 1
    3939
    40 #include "ldb_includes.h"
     40#include "replace.h"
     41#include "system/filesys.h"
     42#include "system/time.h"
    4143#include "ldb.h"
    4244#include "ldb_module.h"
     
    4951
    5052#define LDB_HANDLE_FLAG_DONE_CALLED 1
     53/* call is from an untrusted source - eg. over ldap:// */
     54#define LDB_HANDLE_FLAG_UNTRUSTED   2
    5155
    5256struct ldb_handle {
     
    5660        unsigned flags;
    5761        unsigned nesting;
     62
     63        /* used for debugging */
     64        struct ldb_request *parent;
     65        const char *location;
    5866};
    5967
     
    113121        unsigned int create_perms;
    114122
    115         char *modules_dir;
    116 
    117123        struct tevent_context *ev_ctx;
    118124
     
    120126
    121127        char *partial_debug;
     128
     129        struct poptOption *popt_options;
    122130};
    123131
    124132/* The following definitions come from lib/ldb/common/ldb.c  */
    125 
    126 int ldb_connect_backend(struct ldb_context *ldb, const char *url, const char *options[],
    127                         struct ldb_module **backend_module);
    128 
    129133
    130134extern const struct ldb_module_ops ldb_objectclass_module_ops;
     
    158162
    159163/* The following definitions come from lib/ldb/common/ldb_utf8.c */
    160 char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n);
     164char *ldb_casefold_default(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n);
    161165
    162166void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f);
     
    166170
    167171const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *string);
    168 int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, struct ldb_module *backend, struct ldb_module **out);
    169172int ldb_load_modules(struct ldb_context *ldb, const char *options[]);
    170 int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module);
    171173
    172 struct ldb_val ldb_binary_decode(void *mem_ctx, const char *str);
     174struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str);
     175
     176
     177/* The following definitions come from lib/ldb/common/ldb_options.c  */
     178
     179const char *ldb_options_find(struct ldb_context *ldb, const char *options[],
     180                             const char *option_name);
    173181
    174182#endif
  • trunk/server/source4/lib/ldb/ldb.pc.in

    r414 r745  
    1010Requires.private: tdb
    1111Requires: talloc
    12 Libs: -L${libdir} -lldb
     12Libs: @LIB_RPATH@ -L${libdir} -lldb
    1313Libs.private: @LDAP_LIBS@
    1414Cflags: -I${includedir}
  • trunk/server/source4/lib/ldb/ldb_ldap/ldb_ldap.c

    r414 r745  
    3434 *  Modifications:
    3535 *
    36  *  - description: make the module use asyncronous calls
     36 *  - description: make the module use asynchronous calls
    3737 *    date: Feb 2006
    3838 *    author: Simo Sorce
    3939 */
    4040
    41 #include "ldb_includes.h"
     41#include "replace.h"
     42#include "system/filesys.h"
     43#include "system/time.h"
    4244#include "ldb_module.h"
     45#include "ldb_private.h"
    4346
    4447#define LDAP_DEPRECATED 1
     
    118121                                goto failed;
    119122                        }
    120                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
     123                        mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = (char *)el->values[j].data;
    121124                        mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
    122125                }
     
    254257
    255258        ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope,
    256                             expression,
    257                             discard_const_p(char *, req->op.search.attrs),
    258                             0,
    259                             NULL,
    260                             NULL,
    261                             &tv,
    262                             LDAP_NO_LIMIT,
    263                             &lldb_ac->msgid);
     259                              expression,
     260                              discard_const_p(char *, req->op.search.attrs),
     261                              0,
     262                              NULL,
     263                              NULL,
     264                              &tv,
     265                              LDAP_NO_LIMIT,
     266                              &lldb_ac->msgid);
    264267
    265268        if (ret != LDAP_SUCCESS) {
     
    283286        int ret;
    284287
    285         ldb_module_get_ctx(module);
     288        ldb = ldb_module_get_ctx(module);
    286289
    287290        ldb_request_set_state(req, LDB_ASYNC_PENDING);
     
    322325        int ret;
    323326
    324         ldb_module_get_ctx(module);
     327        ldb = ldb_module_get_ctx(module);
    325328
    326329        ldb_request_set_state(req, LDB_ASYNC_PENDING);
     
    360363        int ret;
    361364
    362         ldb_module_get_ctx(module);
     365        ldb = ldb_module_get_ctx(module);
    363366
    364367        ldb_request_set_state(req, LDB_ASYNC_PENDING);
     
    387390        struct ldb_module *module = lldb_ac->module;
    388391        struct ldb_request *req = lldb_ac->req;
     392        const char *rdn_name;
     393        const struct ldb_val *rdn_val;
    389394        char *old_dn;
    390         char *newrdn;
     395        char *newrdn;
    391396        char *parentdn;
    392397        int ret;
    393398
    394         ldb_module_get_ctx(module);
     399        ldb = ldb_module_get_ctx(module);
    395400
    396401        ldb_request_set_state(req, LDB_ASYNC_PENDING);
     
    401406        }
    402407
    403         newrdn = talloc_asprintf(lldb_ac, "%s=%s",
    404                                  ldb_dn_get_rdn_name(req->op.rename.newdn),
    405                                  ldb_dn_escape_value(lldb, *(ldb_dn_get_rdn_val(req->op.rename.newdn))));
     408        rdn_name = ldb_dn_get_rdn_name(req->op.rename.newdn);
     409        rdn_val = ldb_dn_get_rdn_val(req->op.rename.newdn);
     410
     411        if ((rdn_name != NULL) && (rdn_val != NULL)) {
     412                newrdn = talloc_asprintf(lldb_ac, "%s=%s", rdn_name,
     413                                         rdn_val->length > 0 ? ldb_dn_escape_value(lldb, *rdn_val) : "");
     414        } else {
     415                newrdn = talloc_strdup(lldb_ac, "");
     416        }
    406417        if (!newrdn) {
    407418                return LDB_ERR_OPERATIONS_ERROR;
     
    445456}
    446457
    447 void lldb_request_done(struct lldb_context *ac,
     458static void lldb_request_done(struct lldb_context *ac,
    448459                        struct ldb_control **ctrls, int error)
    449460{
     
    484495        bool request_done;
    485496        bool lret;
     497        unsigned int i;
    486498        int ret;
    487         int i;
    488499
    489500        ldb = ldb_module_get_ctx(ac->module);
     
    503514                        ldbmsg = ldb_msg_new(ac);
    504515                        if (!ldbmsg) {
     516                                ldb_oom(ldb);
    505517                                ret = LDB_ERR_OPERATIONS_ERROR;
    506518                                break;
     
    509521                        dn = ldap_get_dn(lldb->ldap, msg);
    510522                        if (!dn) {
     523                                ldb_oom(ldb);
    511524                                talloc_free(ldbmsg);
    512525                                ret = LDB_ERR_OPERATIONS_ERROR;
     
    515528                        ldbmsg->dn = ldb_dn_new(ldbmsg, ldb, dn);
    516529                        if ( ! ldb_dn_validate(ldbmsg->dn)) {
     530                                ldb_asprintf_errstring(ldb, "Invalid DN '%s' in reply", dn);
    517531                                talloc_free(ldbmsg);
    518532                                ret = LDB_ERR_OPERATIONS_ERROR;
     533                                ldap_memfree(dn);
    519534                                break;
    520535                        }
     
    540555                        ret = ldb_module_send_entry(ac->req, ldbmsg, NULL /* controls not yet supported */);
    541556                        if (ret != LDB_SUCCESS) {
    542 
     557                                ldb_asprintf_errstring(ldb, "entry send failed: %s",
     558                                                       ldb_errstring(ldb));
    543559                                callback_failed = true;
    544560                        }
     
    550566        case LDAP_RES_SEARCH_REFERENCE:
    551567
    552                 if (ldap_parse_result(lldb->ldap, result, &ret,
    553                                         &matcheddnp, &errmsgp,
    554                                         &referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) {
     568                ret = ldap_parse_reference(lldb->ldap, result,
     569                                           &referralsp, &serverctrlsp, 0);
     570                if (ret != LDAP_SUCCESS) {
     571                        ldb_asprintf_errstring(ldb, "ldap reference parse error: %s : %s",
     572                                               ldap_err2string(ret), errmsgp);
    555573                        ret = LDB_ERR_OPERATIONS_ERROR;
    556                 }
    557                 if (ret != LDB_SUCCESS) {
    558574                        break;
    559575                }
    560576                if (referralsp == NULL) {
     577                        ldb_asprintf_errstring(ldb, "empty ldap referrals list");
    561578                        ret = LDB_ERR_PROTOCOL_ERROR;
    562579                        break;
     
    568585                        ret = ldb_module_send_referral(ac->req, referral);
    569586                        if (ret != LDB_SUCCESS) {
     587                                ldb_asprintf_errstring(ldb, "referral send failed: %s",
     588                                                       ldb_errstring(ldb));
    570589                                callback_failed = true;
    571590                                break;
     
    586605                }
    587606                if (ret != LDB_SUCCESS) {
     607                        ldb_asprintf_errstring(ldb, "ldap parse error for type %d: %s : %s",
     608                                               type, ldap_err2string(ret), errmsgp);
    588609                        break;
    589610                }
     
    598619
    599620        default:
     621                ldb_asprintf_errstring(ldb, "unknown ldap return type: %d", type);
    600622                ret = LDB_ERR_PROTOCOL_ERROR;
    601623                break;
     
    799821        default:
    800822                /* no other op supported */
    801                 ret = LDB_ERR_OPERATIONS_ERROR;
     823                ret = LDB_ERR_PROTOCOL_ERROR;
    802824                break;
    803825        }
     
    846868}
    847869
     870
     871/*
     872  optionally perform a bind
     873 */
     874static int lldb_bind(struct ldb_module *module,
     875                     const char *options[])
     876{
     877        const char *bind_mechanism;
     878        struct lldb_private *lldb;
     879        struct ldb_context *ldb = ldb_module_get_ctx(module);
     880        int ret;
     881
     882        bind_mechanism = ldb_options_find(ldb, options, "bindMech");
     883        if (bind_mechanism == NULL) {
     884                /* no bind wanted */
     885                return LDB_SUCCESS;
     886        }
     887
     888        lldb = talloc_get_type(ldb_module_get_private(module), struct lldb_private);
     889
     890        if (strcmp(bind_mechanism, "simple") == 0) {
     891                const char *bind_id, *bind_secret;
     892
     893                bind_id = ldb_options_find(ldb, options, "bindID");
     894                bind_secret = ldb_options_find(ldb, options, "bindSecret");
     895                if (bind_id == NULL || bind_secret == NULL) {
     896                        ldb_asprintf_errstring(ldb, "simple bind requires bindID and bindSecret");
     897                        return LDB_ERR_OPERATIONS_ERROR;
     898                }
     899
     900                ret = ldap_simple_bind_s(lldb->ldap, bind_id, bind_secret);
     901                if (ret != LDAP_SUCCESS) {
     902                        ldb_asprintf_errstring(ldb, "bind failed: %s", ldap_err2string(ret));
     903                        return ret;
     904                }
     905                return LDB_SUCCESS;
     906        }
     907
     908        ldb_asprintf_errstring(ldb, "bind failed: unknown mechanism %s", bind_mechanism);
     909        return LDB_ERR_INAPPROPRIATE_AUTHENTICATION;
     910}
     911
    848912/*
    849913  connect to the database
     
    861925
    862926        module = ldb_module_new(ldb, ldb, "ldb_ldap backend", &lldb_ops);
    863         if (!module) return -1;
     927        if (!module) return LDB_ERR_OPERATIONS_ERROR;
    864928
    865929        lldb = talloc_zero(module, struct lldb_private);
     
    887951
    888952        *_module = module;
    889         return 0;
     953
     954        ret = lldb_bind(module, options);
     955        if (ret != LDB_SUCCESS) {
     956                goto failed;
     957        }
     958
     959
     960        return LDB_SUCCESS;
    890961
    891962failed:
    892963        talloc_free(module);
    893         return -1;
    894 }
    895 
    896 const struct ldb_backend_ops ldb_ldap_backend_ops = {
    897         .name = "ldap",
    898         .connect_fn = lldb_connect
    899 };
    900 
    901 const struct ldb_backend_ops ldb_ldapi_backend_ops = {
    902         .name = "ldapi",
    903         .connect_fn = lldb_connect
    904 };
    905 
    906 const struct ldb_backend_ops ldb_ldaps_backend_ops = {
    907         .name = "ldaps",
    908         .connect_fn = lldb_connect
    909 };
     964        return LDB_ERR_OPERATIONS_ERROR;
     965}
     966
     967/*
     968  initialise the module
     969 */
     970int ldb_ldap_init(const char *version)
     971{
     972        int ret, i;
     973        const char *names[] = { "ldap", "ldaps", "ldapi", NULL };
     974        LDB_MODULE_CHECK_VERSION(version);
     975        for (i=0; names[i]; i++) {
     976                ret = ldb_register_backend(names[i], lldb_connect, false);
     977                if (ret != LDB_SUCCESS) {
     978                        return ret;
     979                }
     980        }
     981        return LDB_SUCCESS;
     982}
  • trunk/server/source4/lib/ldb/ldb_map/ldb_map.c

    r414 r745  
    3636 */
    3737
    38 #include "ldb_includes.h"
     38#include "replace.h"
     39#include "system/filesys.h"
     40#include "system/time.h"
    3941#include "ldb_map.h"
    4042#include "ldb_map_private.h"
     
    257259static const struct ldb_map_objectclass *map_objectclass_find_local(const struct ldb_map_context *data, const char *name)
    258260{
    259         int i;
     261        unsigned int i;
    260262
    261263        for (i = 0; data->objectclass_maps && data->objectclass_maps[i].local_name; i++) {
     
    271273static const struct ldb_map_objectclass *map_objectclass_find_remote(const struct ldb_map_context *data, const char *name)
    272274{
    273         int i;
     275        unsigned int i;
    274276
    275277        for (i = 0; data->objectclass_maps && data->objectclass_maps[i].remote_name; i++) {
     
    285287const struct ldb_map_attribute *map_attr_find_local(const struct ldb_map_context *data, const char *name)
    286288{
    287         int i;
     289        unsigned int i;
    288290
    289291        for (i = 0; data->attribute_maps[i].local_name; i++) {
     
    306308        const struct ldb_map_attribute *map;
    307309        const struct ldb_map_attribute *wildcard = NULL;
    308         int i, j;
     310        unsigned int i, j;
    309311
    310312        for (i = 0; data->attribute_maps[i].local_name; i++) {
     
    315317
    316318                switch (map->type) {
    317                 case MAP_IGNORE:
     319                case LDB_MAP_IGNORE:
    318320                        break;
    319321
    320                 case MAP_KEEP:
     322                case LDB_MAP_KEEP:
    321323                        if (ldb_attr_cmp(map->local_name, name) == 0) {
    322324                                return map;
     
    324326                        break;
    325327
    326                 case MAP_RENAME:
    327                 case MAP_CONVERT:
     328                case LDB_MAP_RENAME:
     329                case LDB_MAP_CONVERT:
    328330                        if (ldb_attr_cmp(map->u.rename.remote_name, name) == 0) {
    329331                                return map;
     
    331333                        break;
    332334
    333                 case MAP_GENERATE:
     335                case LDB_MAP_GENERATE:
    334336                        for (j = 0; map->u.generate.remote_names && map->u.generate.remote_names[j]; j++) {
    335337                                if (ldb_attr_cmp(map->u.generate.remote_names[j], name) == 0) {
     
    357359                return false;
    358360        }
    359         if (map->type == MAP_IGNORE) {
     361        if (map->type == LDB_MAP_IGNORE) {
    360362                return false;
    361363        }
     
    372374
    373375        switch (map->type) {
    374         case MAP_KEEP:
     376        case LDB_MAP_KEEP:
    375377                return talloc_strdup(mem_ctx, attr);
    376378
    377         case MAP_RENAME:
    378         case MAP_CONVERT:
     379        case LDB_MAP_RENAME:
     380        case LDB_MAP_CONVERT:
    379381                return talloc_strdup(mem_ctx, map->u.rename.remote_name);
    380382
     
    391393        }
    392394
    393         if (map->type == MAP_KEEP) {
     395        if (map->type == LDB_MAP_KEEP) {
    394396                return talloc_strdup(mem_ctx, attr);
    395397        }
     
    403405                    const char ***attrs, const char * const *more_attrs)
    404406{
    405         int i, j, k;
     407        unsigned int i, j, k;
    406408
    407409        for (i = 0; *attrs && (*attrs)[i]; i++) /* noop */ ;
     
    430432                                 const struct ldb_map_attribute *map, const struct ldb_val *val)
    431433{
    432         if (map && (map->type == MAP_CONVERT) && (map->u.convert.convert_local)) {
     434        if (map && (map->type == LDB_MAP_CONVERT) && (map->u.convert.convert_local)) {
    433435                return map->u.convert.convert_local(module, mem_ctx, val);
    434436        }
     
    441443                                  const struct ldb_map_attribute *map, const struct ldb_val *val)
    442444{
    443         if (map && (map->type == MAP_CONVERT) && (map->u.convert.convert_remote)) {
     445        if (map && (map->type == LDB_MAP_CONVERT) && (map->u.convert.convert_remote)) {
    444446                return map->u.convert.convert_remote(module, mem_ctx, val);
    445447        }
     
    494496                /* Unknown attribute - leave this RDN as is and hope the best... */
    495497                if (map == NULL) {
    496                         map_type = MAP_KEEP;
     498                        map_type = LDB_MAP_KEEP;
    497499                } else {
    498500                        map_type = map->type;
     
    500502
    501503                switch (map_type) {
    502                 case MAP_IGNORE:
    503                 case MAP_GENERATE:
     504                case LDB_MAP_IGNORE:
     505                case LDB_MAP_GENERATE:
    504506                        ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
    505                                   "MAP_IGNORE/MAP_GENERATE attribute '%s' "
     507                                  "LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' "
    506508                                  "used in DN!", ldb_dn_get_component_name(dn, i));
    507509                        goto failed;
    508510
    509                 case MAP_CONVERT:
     511                case LDB_MAP_CONVERT:
    510512                        if (map->u.convert.convert_local == NULL) {
    511513                                ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
     
    515517                        }
    516518                        /* fall through */
    517                 case MAP_KEEP:
    518                 case MAP_RENAME:
     519                case LDB_MAP_KEEP:
     520                case LDB_MAP_RENAME:
    519521                        name = map_attr_map_local(newdn, map, ldb_dn_get_component_name(dn, i));
    520522                        if (name == NULL) goto failed;
     
    569571                /* Unknown attribute - leave this RDN as is and hope the best... */
    570572                if (map == NULL) {
    571                         map_type = MAP_KEEP;
     573                        map_type = LDB_MAP_KEEP;
    572574                } else {
    573575                        map_type = map->type;
     
    575577
    576578                switch (map_type) {
    577                 case MAP_IGNORE:
    578                 case MAP_GENERATE:
     579                case LDB_MAP_IGNORE:
     580                case LDB_MAP_GENERATE:
    579581                        ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
    580                                   "MAP_IGNORE/MAP_GENERATE attribute '%s' "
     582                                  "LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' "
    581583                                  "used in DN!", ldb_dn_get_component_name(dn, i));
    582584                        goto failed;
    583585
    584                 case MAP_CONVERT:
     586                case LDB_MAP_CONVERT:
    585587                        if (map->u.convert.convert_remote == NULL) {
    586588                                ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
     
    590592                        }
    591593                        /* fall through */
    592                 case MAP_KEEP:
    593                 case MAP_RENAME:
     594                case LDB_MAP_KEEP:
     595                case LDB_MAP_RENAME:
    594596                        name = map_attr_map_remote(newdn, map, ldb_dn_get_component_name(dn, i));
    595597                        if (name == NULL) goto failed;
     
    715717        struct ldb_val val;
    716718        bool found_extensibleObject = false;
    717         int i;
     719        unsigned int i;
    718720
    719721        ldb = ldb_module_get_ctx(module);
     
    790792        struct ldb_message_element *el, *oc;
    791793        struct ldb_val val;
    792         int i;
     794        unsigned int i;
    793795
    794796        ldb = ldb_module_get_ctx(module);
     
    843845static const struct ldb_map_attribute objectclass_convert_map = {
    844846        .local_name = "objectClass",
    845         .type = MAP_CONVERT,
     847        .type = LDB_MAP_CONVERT,
    846848        .u = {
    847849                .convert = {
     
    892894                                        context, callback,
    893895                                        ac->req);
     896        LDB_REQ_SET_LOCATION(req);
    894897        if (ret != LDB_SUCCESS) {
    895898                return NULL;
     
    939942                                context, callback,
    940943                                ac->req);
     944        LDB_REQ_SET_LOCATION(req);
    941945        if (ret != LDB_SUCCESS) {
    942946                goto failed;
     
    958962        {
    959963                .local_name = "dn",
    960                 .type = MAP_CONVERT,
     964                .type = LDB_MAP_CONVERT,
    961965                .u = {
    962966                        .convert = {
     
    974978static const struct ldb_map_attribute objectclass_attribute_map = {
    975979        .local_name = "objectClass",
    976         .type = MAP_GENERATE,
     980        .type = LDB_MAP_GENERATE,
    977981        .convert_operator = map_objectclass_convert_operator,
    978982        .u = {
     
    10441048                         const char * const *wildcard_attributes)
    10451049{
    1046         int i, j, last;
     1050        unsigned int i, j, last;
    10471051        last = 0;
    10481052
  • trunk/server/source4/lib/ldb/ldb_map/ldb_map.h

    r414 r745  
    6060
    6161        enum ldb_map_attr_type {
    62                 MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely.  */
    63                 MAP_KEEP,   /* Keep as is. Same name locally and remotely. */
    64                 MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */
    65                 MAP_CONVERT, /* Rename + convert data */
    66                 MAP_GENERATE /* Use generate function for generating new name/data.
     62                LDB_MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely.  */
     63                LDB_MAP_KEEP,   /* Keep as is. Same name locally and remotely. */
     64                LDB_MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */
     65                LDB_MAP_CONVERT, /* Rename + convert data */
     66                LDB_MAP_GENERATE /* Use generate function for generating new name/data.
    6767                                                Used for generating attributes based on
    6868                                                multiple remote attributes. */
     
    158158                 const char *name);
    159159
    160 int map_add(struct ldb_module *module, struct ldb_request *req);
    161 int map_search(struct ldb_module *module, struct ldb_request *req);
    162 int map_rename(struct ldb_module *module, struct ldb_request *req);
    163 int map_delete(struct ldb_module *module, struct ldb_request *req);
    164 int map_modify(struct ldb_module *module, struct ldb_request *req);
     160int ldb_map_add(struct ldb_module *module, struct ldb_request *req);
     161int ldb_map_search(struct ldb_module *module, struct ldb_request *req);
     162int ldb_map_rename(struct ldb_module *module, struct ldb_request *req);
     163int ldb_map_delete(struct ldb_module *module, struct ldb_request *req);
     164int ldb_map_modify(struct ldb_module *module, struct ldb_request *req);
    165165
    166166#define LDB_MAP_OPS \
    167         .add            = map_add, \
    168         .modify         = map_modify, \
    169         .del            = map_delete, \
    170         .rename         = map_rename, \
    171         .search         = map_search,
     167        .add            = ldb_map_add, \
     168        .modify         = ldb_map_modify, \
     169        .del            = ldb_map_delete, \
     170        .rename         = ldb_map_rename, \
     171        .search         = ldb_map_search,
    172172
    173173#endif /* __LDB_MAP_H__ */
  • trunk/server/source4/lib/ldb/ldb_map/ldb_map_inbound.c

    r414 r745  
    2525*/
    2626
    27 #include "ldb_includes.h"
     27#include "replace.h"
     28#include "system/filesys.h"
     29#include "system/time.h"
    2830#include "ldb_map.h"
    2931#include "ldb_map_private.h"
     
    3739{
    3840        struct ldb_message_element *el;
    39         int i;
     41        unsigned int i;
    4042
    4143        el = talloc_zero(mem_ctx, struct ldb_message_element);
     
    8082
    8183        switch (map->type) {
    82         case MAP_IGNORE:
     84        case LDB_MAP_IGNORE:
    8385                goto local;
    8486
    85         case MAP_CONVERT:
     87        case LDB_MAP_CONVERT:
    8688                if (map->u.convert.convert_local == NULL) {
    8789                        ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
     
    9294                }
    9395                /* fall through */
    94         case MAP_KEEP:
    95         case MAP_RENAME:
     96        case LDB_MAP_KEEP:
     97        case LDB_MAP_RENAME:
    9698                el = ldb_msg_el_map_local(module, remote, map, old);
    9799                break;
    98100
    99         case MAP_GENERATE:
     101        case LDB_MAP_GENERATE:
    100102                if (map->u.generate.generate_remote == NULL) {
    101103                        ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
     
    142144        const struct ldb_map_context *data = map_get_context(module);
    143145        bool ret;
    144         int i;
     146        unsigned int i;
    145147
    146148        for (i = 0; i < msg->num_elements; i++) {
     
    160162        /* const char * const names[]; */
    161163        struct ldb_context *ldb;
    162         int i, ret;
     164        unsigned int i;
     165        int ret;
    163166
    164167        ldb = ldb_module_get_ctx(module);
     
    357360
    358361/* Add a record. */
    359 int map_add(struct ldb_module *module, struct ldb_request *req)
     362int ldb_map_add(struct ldb_module *module, struct ldb_request *req)
    360363{
    361364        const struct ldb_message *msg = req->op.add.message;
     
    363366        struct map_context *ac;
    364367        struct ldb_message *remote_msg;
    365         const char *dn;
    366368        int ret;
    367369
     
    415417                                ac, map_op_remote_callback,
    416418                                req);
     419        LDB_REQ_SET_LOCATION(ac->remote_req);
    417420        if (ret != LDB_SUCCESS) {
    418421                return LDB_ERR_OPERATIONS_ERROR;
     
    427430        /* Store remote DN in 'IS_MAPPED' */
    428431        /* TODO: use GUIDs here instead */
    429         dn = ldb_dn_alloc_linearized(ac->local_msg, remote_msg->dn);
    430         if (ldb_msg_add_string(ac->local_msg, IS_MAPPED, dn) != 0) {
     432        ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
     433                                        remote_msg->dn);
     434        if (ret != LDB_SUCCESS) {
    431435                return LDB_ERR_OPERATIONS_ERROR;
    432436        }
     
    451455                                map_op_local_callback,
    452456                                ac->req);
     457        LDB_REQ_SET_LOCATION(local_req);
    453458        if (ret != LDB_SUCCESS) {
    454459                return LDB_ERR_OPERATIONS_ERROR;
     
    462467
    463468/* Modify a record. */
    464 int map_modify(struct ldb_module *module, struct ldb_request *req)
     469int ldb_map_modify(struct ldb_module *module, struct ldb_request *req)
    465470{
    466471        const struct ldb_message *msg = req->op.mod.message;
     
    522527                                ac, map_op_remote_callback,
    523528                                req);
     529        LDB_REQ_SET_LOCATION(ac->remote_req);
    524530        if (ret != LDB_SUCCESS) {
    525531                return LDB_ERR_OPERATIONS_ERROR;
     
    546552        struct ldb_request *local_req;
    547553        struct ldb_context *ldb;
    548         char *dn;
    549554        int ret;
    550555
     
    559564                        return LDB_ERR_OPERATIONS_ERROR;
    560565                }
    561                 dn = ldb_dn_alloc_linearized(ac->local_msg,
    562                                         ac->remote_req->op.mod.message->dn);
    563                 if (ldb_msg_add_string(ac->local_msg, IS_MAPPED, dn) != 0) {
     566                ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
     567                                                ac->remote_req->op.mod.message->dn);
     568                if (ret != 0) {
    564569                        return LDB_ERR_OPERATIONS_ERROR;
    565570                }
     
    572577                                        map_op_local_callback,
    573578                                        ac->req);
     579                LDB_REQ_SET_LOCATION(local_req);
    574580                if (ret != LDB_SUCCESS) {
    575581                        return LDB_ERR_OPERATIONS_ERROR;
     
    583589                                        map_op_local_callback,
    584590                                        ac->req);
     591                LDB_REQ_SET_LOCATION(local_req);
    585592                if (ret != LDB_SUCCESS) {
    586593                        return LDB_ERR_OPERATIONS_ERROR;
     
    596603
    597604/* Delete a record. */
    598 int map_delete(struct ldb_module *module, struct ldb_request *req)
     605int ldb_map_delete(struct ldb_module *module, struct ldb_request *req)
    599606{
    600607        struct ldb_request *search_req;
     
    629636                                   map_op_remote_callback,
    630637                                   req);
     638        LDB_REQ_SET_LOCATION(ac->remote_req);
    631639        if (ret != LDB_SUCCESS) {
    632640                return LDB_ERR_OPERATIONS_ERROR;
     
    671679                                   map_op_local_callback,
    672680                                   ac->req);
     681        LDB_REQ_SET_LOCATION(local_req);
    673682        if (ret != LDB_SUCCESS) {
    674683                return LDB_ERR_OPERATIONS_ERROR;
     
    682691
    683692/* Rename a record. */
    684 int map_rename(struct ldb_module *module, struct ldb_request *req)
     693int ldb_map_rename(struct ldb_module *module, struct ldb_request *req)
    685694{
    686695        struct ldb_request *search_req;
     
    722731                                   ac, map_op_remote_callback,
    723732                                   req);
     733        LDB_REQ_SET_LOCATION(ac->remote_req);
    724734        if (ret != LDB_SUCCESS) {
    725735                return LDB_ERR_OPERATIONS_ERROR;
     
    765775                                   map_rename_local_callback,
    766776                                   ac->req);
     777        LDB_REQ_SET_LOCATION(local_req);
    767778        if (ret != LDB_SUCCESS) {
    768779                return LDB_ERR_OPERATIONS_ERROR;
  • trunk/server/source4/lib/ldb/ldb_map/ldb_map_outbound.c

    r414 r745  
    2626*/
    2727
    28 #include "ldb_includes.h"
     28#include "replace.h"
     29#include "system/filesys.h"
     30#include "system/time.h"
    2931#include "ldb_map.h"
    3032#include "ldb_map_private.h"
     
    3941        const struct ldb_map_context *data = map_get_context(module);
    4042        const char **result;
    41         int i, last;
     43        unsigned int i, last;
    4244
    4345        if (attrs == NULL)
     
    8284        const struct ldb_map_attribute *map;
    8385        const char *name=NULL;
    84         int i, j, last;
     86        unsigned int i, j, last;
    8587        int ret;
    8688
     
    125127
    126128                switch (map->type) {
    127                 case MAP_IGNORE:
     129                case LDB_MAP_IGNORE:
    128130                        continue;
    129131
    130                 case MAP_KEEP:
     132                case LDB_MAP_KEEP:
    131133                        name = attrs[i];
    132134                        goto named;
    133135
    134                 case MAP_RENAME:
    135                 case MAP_CONVERT:
     136                case LDB_MAP_RENAME:
     137                case LDB_MAP_CONVERT:
    136138                        name = map->u.rename.remote_name;
    137139                        goto named;
    138140
    139                 case MAP_GENERATE:
     141                case LDB_MAP_GENERATE:
    140142                        /* Add all remote names of "generate" attrs */
    141143                        for (j = 0; map->u.generate.remote_names[j]; j++) {
     
    220222                                                         const struct ldb_message_element *old)
    221223{
     224        const struct ldb_map_context *data = map_get_context(module);
     225        const char *local_attr_name = attr_name;
    222226        struct ldb_message_element *el;
    223         int i;
     227        unsigned int i;
    224228
    225229        el = talloc_zero(mem_ctx, struct ldb_message_element);
     
    236240        }
    237241
    238         el->name = talloc_strdup(el, attr_name);
     242        for (i = 0; data->attribute_maps[i].local_name; i++) {
     243                struct ldb_map_attribute *am = &data->attribute_maps[i];
     244                if ((am->type == LDB_MAP_RENAME &&
     245                        !strcmp(am->u.rename.remote_name, attr_name))
     246                    || (am->type == LDB_MAP_CONVERT &&
     247                        !strcmp(am->u.convert.remote_name, attr_name))) {
     248
     249                        local_attr_name = am->local_name;
     250                        break;
     251                }
     252        }
     253
     254        el->name = talloc_strdup(el, local_attr_name);
    239255        if (el->name == NULL) {
    240256                talloc_free(el);
     
    282298
    283299        switch (map->type) {
    284         case MAP_IGNORE:
    285                 break;
    286         case MAP_CONVERT:
     300        case LDB_MAP_IGNORE:
     301                break;
     302        case LDB_MAP_CONVERT:
    287303                remote_name = map->u.convert.remote_name;
    288304                break;
    289         case MAP_KEEP:
     305        case LDB_MAP_KEEP:
    290306                remote_name = attr_name;
    291307                break;
    292         case MAP_RENAME:
     308        case LDB_MAP_RENAME:
    293309                remote_name = map->u.rename.remote_name;
    294310                break;
    295         case MAP_GENERATE:
     311        case LDB_MAP_GENERATE:
    296312                break;
    297313        }
    298314
    299315        switch (map->type) {
    300         case MAP_IGNORE:
     316        case LDB_MAP_IGNORE:
    301317                return LDB_SUCCESS;
    302318
    303         case MAP_CONVERT:
     319        case LDB_MAP_CONVERT:
    304320                if (map->u.convert.convert_remote == NULL) {
    305321                        ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
     
    310326                }
    311327                /* fall through */
    312         case MAP_KEEP:
    313         case MAP_RENAME:
     328        case LDB_MAP_KEEP:
     329        case LDB_MAP_RENAME:
    314330                old = ldb_msg_find_element(remote, remote_name);
    315331                if (old) {
     
    320336                break;
    321337
    322         case MAP_GENERATE:
     338        case LDB_MAP_GENERATE:
    323339                if (map->u.generate.generate_local == NULL) {
    324340                        ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
     
    351367        const struct ldb_map_attribute *map = map_attr_find_local(data, "*");
    352368        struct ldb_message_element *el=NULL;
    353         int i, ret;
     369        unsigned int i;
     370        int ret;
    354371
    355372        /* Perhaps we have a mapping for "*" */
    356         if (map && map->type == MAP_KEEP) {
     373        if (map && map->type == LDB_MAP_KEEP) {
    357374                /* We copy everything over, and hope that anything with a
    358375                   more specific rule is overwritten */
     
    393410static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
    394411{
    395         int i, ret;
     412        unsigned int i;
     413        int ret;
    396414
    397415        for (i = 0; i < msg2->num_elements; i++) {
     
    409427                                struct ldb_message *remote)
    410428{
    411         int i, ret;
     429        unsigned int i;
     430        int ret;
    412431        const char * const *attrs = ac->all_attrs;
    413432        if (!attrs) {
     
    521540{
    522541        const char **new_attrs;
    523         int i, ret;
     542        unsigned int i;
     543        int ret;
    524544
    525545        if (tree == NULL) {
     
    548568                return 0;
    549569        }
    550 
    551         return -1;
    552570}
    553571
     
    589607static int map_subtree_select_local_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
    590608{
    591         int i, j, ret=0;
     609        unsigned int i, j;
     610        int ret=0;
    592611
    593612        /* Prepare new tree */
     
    712731static int map_subtree_collect_remote_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
    713732{
    714         int i, j, ret=0;
     733        unsigned int i, j;
     734        int ret=0;
    715735
    716736        /* Prepare new tree */
     
    773793        **new = *tree;
    774794       
    775         if (map->type == MAP_KEEP) {
     795        if (map->type == LDB_MAP_KEEP) {
    776796                /* Nothing to do here */
    777797                return 0;
     
    815835        }
    816836
    817         if (map->type == MAP_RENAME) {
     837        if (map->type == LDB_MAP_RENAME) {
    818838                /* Nothing more to do here, the attribute has been renamed */
    819839                return 0;
     
    898918        }
    899919
    900         if (map->type == MAP_GENERATE) {
     920        if (map->type == LDB_MAP_GENERATE) {
    901921                ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
    902922                          "Skipping attribute '%s': "
     
    10521072        const char * const *attrs;
    10531073        struct ldb_context *ldb;
    1054         int i;
     1074        unsigned int i;
     1075        int ret;
     1076        bool matched;
    10551077
    10561078        ldb = ldb_module_get_ctx(ac->module);
    10571079
    10581080        /* Merged result doesn't match original query, skip */
    1059         if (!ldb_match_msg(ldb, ares->message,
    1060                            ac->req->op.search.tree,
    1061                            ac->req->op.search.base,
    1062                            ac->req->op.search.scope)) {
     1081        ret = ldb_match_msg_error(ldb, ares->message,
     1082                                  ac->req->op.search.tree,
     1083                                  ac->req->op.search.base,
     1084                                  ac->req->op.search.scope,
     1085                                  &matched);
     1086        if (ret != LDB_SUCCESS) return ret;
     1087        if (!matched) {
    10631088                ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
    10641089                          "Skipping record '%s': "
     
    10901115
    10911116/* Search a record. */
    1092 int map_search(struct ldb_module *module, struct ldb_request *req)
     1117int ldb_map_search(struct ldb_module *module, struct ldb_request *req)
    10931118{
    10941119        struct ldb_parse_tree *remote_tree;
     
    11861211                                      ac, map_remote_search_callback,
    11871212                                      req);
     1213        LDB_REQ_SET_LOCATION(remote_req);
    11881214        if (ret != LDB_SUCCESS) {
    11891215                return LDB_ERR_OPERATIONS_ERROR;
     
    12621288                }
    12631289
    1264                 talloc_free(ares);
     1290                ac->remote_done_ares = talloc_steal(ac, ares);
    12651291
    12661292                ret = map_search_local(ac);
     
    13341360
    13351361        case LDB_REPLY_DONE:
     1362                /* We don't need the local 'ares', but we will use the remote one from below */
    13361363                talloc_free(ares);
    13371364
     
    13721399                 * finish operations for this module */
    13731400                return ldb_module_done(ac->req,
    1374                                         ac->r_current->remote->controls,
    1375                                         ac->r_current->remote->response,
    1376                                         ac->r_current->remote->error);
     1401                                        ac->remote_done_ares->controls,
     1402                                        ac->remote_done_ares->response,
     1403                                        ac->remote_done_ares->error);
    13771404        }
    13781405
  • trunk/server/source4/lib/ldb/ldb_map/ldb_map_private.h

    r414 r745  
    1 #include "ldb_includes.h"
     1#include "replace.h"
     2#include "system/filesys.h"
     3#include "system/time.h"
    24
    35/* A handy macro to report Out of Memory conditions */
     
    3840        struct map_reply *r_list;
    3941        struct map_reply *r_current;
     42
     43        /* The response continaing any controls the remote server gave */
     44        struct ldb_reply *remote_done_ares;
    4045};
    4146
  • trunk/server/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c

    r414 r745  
    256256        char *ret = NULL;
    257257        char *attr;
    258         int i;
     258        unsigned int i;
    259259
    260260        ldb = ldb_module_get_ctx(module);
     
    558558
    559559/*
    560  * This is a bad hack to support ldap style comparisons whithin sqlite.
     560 * This is a bad hack to support ldap style comparisons within sqlite.
    561561 * val is the attribute in the row currently under test
    562562 * func is the desired test "<=" ">=" "~" ":"
     
    668668        struct ldb_message *msg;
    669669        long long eid;
    670         int i, ret;
     670        unsigned int i;
     671        int ret;
    671672
    672673        ac = talloc_get_type(result, struct lsql_context);
     
    687688                 * except the first time */
    688689                if (ac->current_eid != 0) {
    689                         msg = ldb_msg_canonicalize(ldb, msg);
    690                         if (!msg) return SQLITE_ABORT;
     690                        ret = ldb_msg_normalize(ldb, ac->req, msg, &msg);
     691                        if (ret != LDB_SUCCESS) {
     692                                return SQLITE_ABORT;
     693                        }
    691694
    692695                        ret = ldb_module_send_entry(ac->req, msg, NULL);
    693696                        if (ret != LDB_SUCCESS) {
    694697                                ac->callback_failed = true;
     698                                /* free msg object */
     699                                TALLOC_FREE(msg);
    695700                                return SQLITE_ABORT;
    696701                        }
     702
     703                        /* free msg object */
     704                        TALLOC_FREE(msg);
    697705                }
    698706
     
    960968        /* complete the last message if any */
    961969        if (ctx->ares) {
    962                 ctx->ares->message = ldb_msg_canonicalize(ldb, ctx->ares->message);
    963                 if (ctx->ares->message == NULL) {
     970                ret = ldb_msg_normalize(ldb, ctx->ares,
     971                                        ctx->ares->message,
     972                                        &ctx->ares->message);
     973                if (ret != LDB_SUCCESS) {
    964974                        return LDB_ERR_OPERATIONS_ERROR;
    965975                }
     
    987997        char *errmsg;
    988998        char *query;
    989         int i;
     999        unsigned int i;
    9901000        int ret;
    9911001
     
    10441054                const struct ldb_schema_attribute *a;
    10451055                char *attr;
    1046                 int j;
     1056                unsigned int j;
    10471057
    10481058                /* Get a case-folded copy of the attribute name */
     
    10531063
    10541064                a = ldb_schema_attribute_by_name(ldb, el->name);
     1065
     1066                if (el->num_value == 0) {
     1067                        ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illegal)",
     1068                                               el->name, ldb_dn_get_linearized(msg->dn));
     1069                        return LDB_ERR_CONSTRAINT_VIOLATION;
     1070                }
    10551071
    10561072                /* For each value of the specified attribute name... */
     
    10981114        struct ldb_context *ldb;
    10991115        struct ldb_message *msg = req->op.mod.message;
    1100         long long eid;
     1116        long long eid;
    11011117        char *errmsg;
    1102         int i;
     1118        unsigned int i;
    11031119        int ret;
    11041120
     
    11241140                char *attr;
    11251141                char *mod;
    1126                 int j;
     1142                unsigned int j;
    11271143
    11281144                /* Get a case-folded copy of the attribute name */
     
    11371153
    11381154                case LDB_FLAG_MOD_REPLACE:
     1155
     1156                        for (j=0; j<el->num_values; j++) {
     1157                                if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
     1158                                        ldb_asprintf_errstring(ldb, "%s: value #%d provided more than once", el->name, j);
     1159                                        return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     1160                                }
     1161                        }
    11391162
    11401163                        /* remove all attributes before adding the replacements */
     
    11601183
    11611184                case LDB_FLAG_MOD_ADD:
    1162 #warning "We should throw an error if no value is provided!"
     1185
     1186                        if (el->num_values == 0) {
     1187                                ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illigal)",
     1188                                                       el->name, ldb_dn_get_linearized(msg->dn));
     1189                                return LDB_ERR_CONSTRAINT_VIOLATION;
     1190                        }
     1191
    11631192                        /* For each value of the specified attribute name... */
    11641193                        for (j = 0; j < el->num_values; j++) {
     
    14921521        default:
    14931522                /* no other op supported */
    1494                 ret = LDB_ERR_UNWILLING_TO_PERFORM;
     1523                ret = LDB_ERR_PROTOCOL_ERROR;
    14951524        }
    14961525
     
    15101539        struct timeval tv;
    15111540
    1512         if (check_critical_controls(req->controls)) {
     1541        if (ldb_check_critical_controls(req->controls)) {
    15131542                return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
    15141543        }
     
    18461875        struct ldb_module *module;
    18471876        struct lsqlite3_private *lsqlite3;
    1848         int i, ret;
     1877        unsigned int i;
     1878        int ret;
    18491879
    18501880        module = ldb_module_new(ldb, ldb, "ldb_sqlite3 backend", &lsqlite3_ops);
    1851         if (!module) return -1;
     1881        if (!module) return LDB_ERR_OPERATIONS_ERROR;
    18521882
    18531883        lsqlite3 = talloc(module, struct lsqlite3_private);
     
    18931923
    18941924        *_module = module;
    1895         return 0;
     1925        return LDB_SUCCESS;
    18961926
    18971927failed:
     
    19001930        }
    19011931        talloc_free(lsqlite3);
    1902         return -1;
    1903 }
    1904 
    1905 const struct ldb_backend_ops ldb_sqlite3_backend_ops = {
    1906         .name = "sqlite3",
    1907         .connect_fn = lsqlite3_connect
    1908 };
     1932        return LDB_ERR_OPERATIONS_ERROR;
     1933}
     1934
     1935int ldb_sqlite3_init(const char *version)
     1936{
     1937        LDB_MODULE_CHECK_VERSION(version);
     1938        return ldb_register_backend("sqlite3", lsqlite3_connect, false);
     1939}
  • trunk/server/source4/lib/ldb/ldb_tdb/ldb_cache.c

    r414 r745  
    6161        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    6262        struct ldb_message *msg;
    63         int i;
     63        unsigned int i;
    6464
    6565        ldb = ldb_module_get_ctx(module);
     
    8484static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v)
    8585{
    86         int i;
     86        unsigned int i;
    8787        unsigned value = 0;
    8888        for (i=0;i<el->num_values;i++) {
    89                 int j;
     89                unsigned int j;
    9090                for (j=0;ltdb_valid_attr_flags[j].name;j++) {
    9191                        if (strcmp(ltdb_valid_attr_flags[j].name,
     
    113113        struct ldb_message *msg = ltdb->cache->attributes;
    114114        struct ldb_dn *dn;
    115         int i, r;
     115        unsigned int i;
     116        int r;
    116117
    117118        ldb = ldb_module_get_ctx(module);
     
    120121                /* we skip loading the @ATTRIBUTES record when a module is supplying
    121122                   its own attribute handling */
    122                 return LDB_SUCCESS;
     123                return 0;
    123124        }
    124125
     
    203204        ltdb->sequence_number = atof(initial_sequence_number);
    204205
    205         msg = talloc(ltdb, struct ldb_message);
     206        msg = ldb_msg_new(ltdb);
    206207        if (msg == NULL) {
    207208                goto failed;
     
    287288                ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
    288289                if (ltdb->cache == NULL) goto failed;
    289                 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
    290                 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
     290                ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
     291                ltdb->cache->attributes = ldb_msg_new(ltdb->cache);
    291292                if (ltdb->cache->indexlist == NULL ||
    292293                    ltdb->cache->attributes == NULL) {
     
    295296        }
    296297
    297         baseinfo = talloc(ltdb->cache, struct ldb_message);
     298        baseinfo = ldb_msg_new(ltdb->cache);
    298299        if (baseinfo == NULL) goto failed;
    299300
    300         baseinfo_dn = ldb_dn_new(module, ldb, LTDB_BASEINFO);
     301        baseinfo_dn = ldb_dn_new(baseinfo, ldb, LTDB_BASEINFO);
    301302        if (baseinfo_dn == NULL) goto failed;
    302303
     
    327328
    328329        /* Read an interpret database options */
    329         options = talloc(ltdb->cache, struct ldb_message);
     330        options = ldb_msg_new(ltdb->cache);
    330331        if (options == NULL) goto failed;
    331332
     
    348349        memset(&ltdb->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute));
    349350
    350         ltdb_attributes_unload(module);
    351 
    352351        talloc_free(ltdb->cache->indexlist);
    353 
    354         ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
    355         ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
     352        ltdb_attributes_unload(module); /* calls internally "talloc_free" */
     353
     354        ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
     355        ltdb->cache->attributes = ldb_msg_new(ltdb->cache);
    356356        if (ltdb->cache->indexlist == NULL ||
    357357            ltdb->cache->attributes == NULL) {
    358358                goto failed;
    359359        }
     360        ltdb->cache->one_level_indexes = false;
     361        ltdb->cache->attribute_indexes = false;
    360362           
    361363        indexlist_dn = ldb_dn_new(module, ldb, LTDB_INDEXLIST);
     
    367369        }
    368370
     371        if (ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXONE) != NULL) {
     372                ltdb->cache->one_level_indexes = true;
     373        }
     374        if (ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR) != NULL) {
     375                ltdb->cache->attribute_indexes = true;
     376        }
     377
    369378        if (ltdb_attributes_load(module) == -1) {
    370379                goto failed;
     
    374383        talloc_free(options);
    375384        talloc_free(baseinfo);
    376         talloc_free(baseinfo_dn);
    377385        talloc_free(indexlist_dn);
    378386        return 0;
     
    381389        talloc_free(options);
    382390        talloc_free(baseinfo);
    383         talloc_free(baseinfo_dn);
    384391        talloc_free(indexlist_dn);
    385392        return -1;
     
    405412        ldb = ldb_module_get_ctx(module);
    406413
    407         msg = talloc(ltdb, struct ldb_message);
     414        msg = ldb_msg_new(ltdb);
    408415        if (msg == NULL) {
    409416                errno = ENOMEM;
     
    413420        s = talloc_asprintf(msg, "%llu", ltdb->sequence_number+1);
    414421        if (!s) {
     422                talloc_free(msg);
    415423                errno = ENOMEM;
    416424                return LDB_ERR_OPERATIONS_ERROR;
     
    449457        s = ldb_timestring(msg, t);
    450458        if (s == NULL) {
     459                talloc_free(msg);
    451460                return LDB_ERR_OPERATIONS_ERROR;
    452461        }
     
    455464        val_time.length = strlen(s);
    456465
    457         ret = ltdb_modify_internal(module, msg);
     466        ret = ltdb_modify_internal(module, msg, NULL);
    458467
    459468        talloc_free(msg);
     
    472481int ltdb_check_at_attributes_values(const struct ldb_val *value)
    473482{
    474         int i;
     483        unsigned int i;
    475484
    476485        for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) {
  • trunk/server/source4/lib/ldb/ldb_tdb/ldb_index.c

    r414 r745  
    22   ldb database library
    33
    4    Copyright (C) Andrew Tridgell  2004
     4   Copyright (C) Andrew Tridgell  2004-2009
    55
    66     ** NOTE! The following LGPL license applies to the ldb
     
    3333
    3434#include "ldb_tdb.h"
    35 #include "dlinklist.h"
    36 
    37 /*
    38   the idxptr code is a bit unusual. The way it works is to replace
    39   @IDX elements in records during a transaction with @IDXPTR
    40   elements. The @IDXPTR elements don't contain the actual index entry
    41   values, but contain a pointer to a linked list of values.
    42 
    43   This means we are storing pointers in a database, which is normally
    44   not allowed, but in this case we are storing them only for the
    45   duration of a transaction, and re-writing them into the normal @IDX
    46   format at the end of the transaction. That means no other processes
    47   are ever exposed to the @IDXPTR values.
    48 
    49   The advantage is that the linked list doesn't cause huge
    50   fragmentation during a transaction. Without the @IDXPTR method we
    51   often ended up with a ldb that was between 10x and 100x larger then
    52   it needs to be due to massive fragmentation caused by re-writing
    53   @INDEX records many times during indexing.
    54  */
    55 struct ldb_index_pointer {
    56         struct ldb_index_pointer *next, *prev;
    57         struct ldb_val value;
     35
     36struct dn_list {
     37        unsigned int count;
     38        struct ldb_val *dn;
    5839};
    5940
    6041struct ltdb_idxptr {
    61         int num_dns;
    62         const char **dn_list;
    63         bool repack;
     42        struct tdb_context *itdb;
     43        int error;
    6444};
    6545
    66 /*
    67   add to the list of DNs that need to be fixed on transaction end
    68  */
    69 static int ltdb_idxptr_add(struct ldb_module *module, const struct ldb_message *msg)
    70 {
    71         void *data = ldb_module_get_private(module);
    72         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    73         ltdb->idxptr->dn_list = talloc_realloc(ltdb->idxptr, ltdb->idxptr->dn_list,
    74                                                const char *, ltdb->idxptr->num_dns+1);
    75         if (ltdb->idxptr->dn_list == NULL) {
    76                 ltdb->idxptr->num_dns = 0;
    77                 return LDB_ERR_OPERATIONS_ERROR;
    78         }
    79         ltdb->idxptr->dn_list[ltdb->idxptr->num_dns] =
    80                 talloc_strdup(ltdb->idxptr->dn_list, ldb_dn_get_linearized(msg->dn));
    81         if (ltdb->idxptr->dn_list[ltdb->idxptr->num_dns] == NULL) {
    82                 return LDB_ERR_OPERATIONS_ERROR;
    83         }
    84         ltdb->idxptr->num_dns++;
    85         return LDB_SUCCESS;
    86 }
    87 
    88 /* free an idxptr record */
    89 static int ltdb_free_idxptr(struct ldb_module *module, struct ldb_message_element *el)
    90 {
    91         struct ldb_val val;
    92         struct ldb_index_pointer *ptr;
    93 
    94         if (el->num_values != 1) {
    95                 return LDB_ERR_OPERATIONS_ERROR;
    96         }
    97 
    98         val = el->values[0];
    99         if (val.length != sizeof(void *)) {
    100                 return LDB_ERR_OPERATIONS_ERROR;
    101         }
    102 
    103         ptr = *(struct ldb_index_pointer **)val.data;
    104         if (talloc_get_type(ptr, struct ldb_index_pointer) != ptr) {
    105                 return LDB_ERR_OPERATIONS_ERROR;
    106         }
    107 
    108         while (ptr) {
    109                 struct ldb_index_pointer *tmp = ptr;
    110                 DLIST_REMOVE(ptr, ptr);
    111                 talloc_free(tmp);
    112         }
    113 
    114         return LDB_SUCCESS;
    115 }
    116 
    117 
    118 /* convert from the IDXPTR format to a ldb_message_element format */
    119 static int ltdb_convert_from_idxptr(struct ldb_module *module, struct ldb_message_element *el)
    120 {
    121         struct ldb_val val;
    122         struct ldb_index_pointer *ptr, *tmp;
    123         int i;
    124         struct ldb_val *val2;
    125 
    126         if (el->num_values != 1) {
    127                 return LDB_ERR_OPERATIONS_ERROR;
    128         }
    129 
    130         val = el->values[0];
    131         if (val.length != sizeof(void *)) {
    132                 return LDB_ERR_OPERATIONS_ERROR;
    133         }
    134 
    135         ptr = *(struct ldb_index_pointer **)val.data;
    136         if (talloc_get_type(ptr, struct ldb_index_pointer) != ptr) {
    137                 return LDB_ERR_OPERATIONS_ERROR;
    138         }
    139 
    140         /* count the length of the list */
    141         for (i=0, tmp = ptr; tmp; tmp=tmp->next) {
    142                 i++;
    143         }
    144 
    145         /* allocate the new values array */
    146         val2 = talloc_realloc(NULL, el->values, struct ldb_val, i);
    147         if (val2 == NULL) {
    148                 return LDB_ERR_OPERATIONS_ERROR;
    149         }
    150         el->values = val2;
    151         el->num_values = i;
    152 
    153         /* populate the values array */
    154         for (i=0, tmp = ptr; tmp; tmp=tmp->next, i++) {
    155                 el->values[i].length = tmp->value.length;
    156                 /* we need to over-allocate here as there are still some places
    157                    in ldb that rely on null termination. */
    158                 el->values[i].data = talloc_size(el->values, tmp->value.length+1);
    159                 if (el->values[i].data == NULL) {
    160                         return LDB_ERR_OPERATIONS_ERROR;
    161                 }
    162                 memcpy(el->values[i].data, tmp->value.data, tmp->value.length);
    163                 el->values[i].data[tmp->value.length] = 0;
    164         }
    165 
    166         /* update the name */
    167         el->name = LTDB_IDX;
    168 
    169         return LDB_SUCCESS;
    170 }
    171 
    172 
    173 /* convert to the IDXPTR format from a ldb_message_element format */
    174 static int ltdb_convert_to_idxptr(struct ldb_module *module, struct ldb_message_element *el)
    175 {
    176         struct ldb_index_pointer *ptr, *tmp;
    177         int i;
    178         struct ldb_val *val2;
    179         void *data = ldb_module_get_private(module);
    180         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    181 
    182         ptr = NULL;
    183 
    184         for (i=0;i<el->num_values;i++) {
    185                 tmp = talloc(ltdb->idxptr, struct ldb_index_pointer);
    186                 if (tmp == NULL) {
    187                         return LDB_ERR_OPERATIONS_ERROR;
    188                 }
    189                 tmp->value = el->values[i];
    190                 tmp->value.data = talloc_memdup(tmp, tmp->value.data, tmp->value.length);
    191                 if (tmp->value.data == NULL) {
    192                         return LDB_ERR_OPERATIONS_ERROR;
    193                 }
    194                 DLIST_ADD(ptr, tmp);
    195         }
    196 
    197         /* allocate the new values array */
    198         val2 = talloc_realloc(NULL, el->values, struct ldb_val, 1);
    199         if (val2 == NULL) {
    200                 return LDB_ERR_OPERATIONS_ERROR;
    201         }
    202         el->values = val2;
    203         el->num_values = 1;
    204 
    205         el->values[0].data = talloc_memdup(el->values, &ptr, sizeof(ptr));
    206         el->values[0].length = sizeof(ptr);
    207 
    208         /* update the name */
    209         el->name = LTDB_IDXPTR;
    210 
    211         return LDB_SUCCESS;
    212 }
    213 
     46/* we put a @IDXVERSION attribute on index entries. This
     47   allows us to tell if it was written by an older version
     48*/
     49#define LTDB_INDEXING_VERSION 2
    21450
    21551/* enable the idxptr mode when transactions start */
    21652int ltdb_index_transaction_start(struct ldb_module *module)
    21753{
    218         void *data = ldb_module_get_private(module);
    219         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    220         ltdb->idxptr = talloc_zero(module, struct ltdb_idxptr);
     54        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     55        ltdb->idxptr = talloc_zero(ltdb, struct ltdb_idxptr);
    22156        return LDB_SUCCESS;
    22257}
    22358
    224 /*
    225   a wrapper around ltdb_search_dn1() which translates pointer based index records
    226   and maps them into normal ldb message structures
    227  */
    228 static int ltdb_search_dn1_index(struct ldb_module *module,
    229                                 struct ldb_dn *dn, struct ldb_message *msg)
    230 {
    231         int ret, i;
     59/* compare two DN entries in a dn_list. Take account of possible
     60 * differences in string termination */
     61static int dn_list_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
     62{
     63        if (v1->length > v2->length && v1->data[v2->length] != 0) {
     64                return -1;
     65        }
     66        if (v1->length < v2->length && v2->data[v1->length] != 0) {
     67                return 1;
     68        }
     69        return strncmp((char *)v1->data, (char *)v2->data, v1->length);
     70}
     71
     72
     73/*
     74  find a entry in a dn_list, using a ldb_val. Uses a case sensitive
     75  comparison with the dn returns -1 if not found
     76 */
     77static int ltdb_dn_list_find_val(const struct dn_list *list, const struct ldb_val *v)
     78{
     79        unsigned int i;
     80        for (i=0; i<list->count; i++) {
     81                if (dn_list_cmp(&list->dn[i], v) == 0) return i;
     82        }
     83        return -1;
     84}
     85
     86/*
     87  find a entry in a dn_list. Uses a case sensitive comparison with the dn
     88  returns -1 if not found
     89 */
     90static int ltdb_dn_list_find_str(struct dn_list *list, const char *dn)
     91{
     92        struct ldb_val v;
     93        v.data = discard_const_p(unsigned char, dn);
     94        v.length = strlen(dn);
     95        return ltdb_dn_list_find_val(list, &v);
     96}
     97
     98/*
     99  this is effectively a cast function, but with lots of paranoia
     100  checks and also copes with CPUs that are fussy about pointer
     101  alignment
     102 */
     103static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec, bool check_parent)
     104{
     105        struct dn_list *list;
     106        if (rec.dsize != sizeof(void *)) {
     107                ldb_asprintf_errstring(ldb_module_get_ctx(module),
     108                                       "Bad data size for idxptr %u", (unsigned)rec.dsize);
     109                return NULL;
     110        }
     111        /* note that we can't just use a cast here, as rec.dptr may
     112           not be aligned sufficiently for a pointer. A cast would cause
     113           platforms like some ARM CPUs to crash */
     114        memcpy(&list, rec.dptr, sizeof(void *));
     115        list = talloc_get_type(list, struct dn_list);
     116        if (list == NULL) {
     117                ldb_asprintf_errstring(ldb_module_get_ctx(module),
     118                                       "Bad type '%s' for idxptr",
     119                                       talloc_get_name(list));
     120                return NULL;
     121        }
     122        if (check_parent && list->dn && talloc_parent(list->dn) != list) {
     123                ldb_asprintf_errstring(ldb_module_get_ctx(module),
     124                                       "Bad parent '%s' for idxptr",
     125                                       talloc_get_name(talloc_parent(list->dn)));
     126                return NULL;
     127        }
     128        return list;
     129}
     130
     131/*
     132  return the @IDX list in an index entry for a dn as a
     133  struct dn_list
     134 */
     135static int ltdb_dn_list_load(struct ldb_module *module,
     136                             struct ldb_dn *dn, struct dn_list *list)
     137{
     138        struct ldb_message *msg;
     139        int ret;
     140        struct ldb_message_element *el;
     141        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     142        TDB_DATA rec;
     143        struct dn_list *list2;
     144        TDB_DATA key;
     145
     146        list->dn = NULL;
     147        list->count = 0;
     148
     149        /* see if we have any in-memory index entries */
     150        if (ltdb->idxptr == NULL ||
     151            ltdb->idxptr->itdb == NULL) {
     152                goto normal_index;
     153        }
     154
     155        key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
     156        key.dsize = strlen((char *)key.dptr);
     157
     158        rec = tdb_fetch(ltdb->idxptr->itdb, key);
     159        if (rec.dptr == NULL) {
     160                goto normal_index;
     161        }
     162
     163        /* we've found an in-memory index entry */
     164        list2 = ltdb_index_idxptr(module, rec, true);
     165        if (list2 == NULL) {
     166                free(rec.dptr);
     167                return LDB_ERR_OPERATIONS_ERROR;
     168        }
     169        free(rec.dptr);
     170
     171        *list = *list2;
     172        return LDB_SUCCESS;
     173
     174normal_index:
     175        msg = ldb_msg_new(list);
     176        if (msg == NULL) {
     177                return LDB_ERR_OPERATIONS_ERROR;
     178        }
     179
    232180        ret = ltdb_search_dn1(module, dn, msg);
    233181        if (ret != LDB_SUCCESS) {
     182                talloc_free(msg);
    234183                return ret;
    235184        }
    236185
    237         /* if this isn't a @INDEX record then don't munge it */
    238         if (strncmp(ldb_dn_get_linearized(msg->dn), LTDB_INDEX ":", strlen(LTDB_INDEX) + 1) != 0) {
    239                 return LDB_ERR_OPERATIONS_ERROR;
    240         }
    241 
    242         for (i=0;i<msg->num_elements;i++) {
    243                 struct ldb_message_element *el = &msg->elements[i];
    244                 if (strcmp(el->name, LTDB_IDXPTR) == 0) {
    245                         ret = ltdb_convert_from_idxptr(module, el);
    246                         if (ret != LDB_SUCCESS) {
    247                                 return ret;
    248                         }
    249                 }
    250         }
    251 
    252         return ret;
    253 }
    254 
    255 
    256 
    257 /*
    258   fixup the idxptr for one DN
    259  */
    260 static int ltdb_idxptr_fix_dn(struct ldb_module *module, const char *strdn)
    261 {
    262         struct ldb_context *ldb;
    263         struct ldb_dn *dn;
    264         struct ldb_message *msg = ldb_msg_new(module);
     186        /* TODO: check indexing version number */
     187
     188        el = ldb_msg_find_element(msg, LTDB_IDX);
     189        if (!el) {
     190                talloc_free(msg);
     191                return LDB_SUCCESS;
     192        }
     193
     194        /* we avoid copying the strings by stealing the list */
     195        list->dn = talloc_steal(list, el->values);
     196        list->count = el->num_values;
     197
     198        return LDB_SUCCESS;
     199}
     200
     201
     202/*
     203  save a dn_list into a full @IDX style record
     204 */
     205static int ltdb_dn_list_store_full(struct ldb_module *module, struct ldb_dn *dn,
     206                                   struct dn_list *list)
     207{
     208        struct ldb_message *msg;
    265209        int ret;
    266210
    267         ldb = ldb_module_get_ctx(module);
    268 
    269         dn = ldb_dn_new(msg, ldb, strdn);
    270         if (ltdb_search_dn1_index(module, dn, msg) == LDB_SUCCESS) {
    271                 ret = ltdb_store(module, msg, TDB_REPLACE);
    272         }
     211        if (list->count == 0) {
     212                ret = ltdb_delete_noindex(module, dn);
     213                if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     214                        return LDB_SUCCESS;
     215                }
     216                return ret;
     217        }
     218
     219        msg = ldb_msg_new(module);
     220        if (!msg) {
     221                return ldb_module_oom(module);
     222        }
     223
     224        ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u", LTDB_INDEXING_VERSION);
     225        if (ret != LDB_SUCCESS) {
     226                talloc_free(msg);
     227                return ldb_module_oom(module);
     228        }
     229
     230        msg->dn = dn;
     231        if (list->count > 0) {
     232                struct ldb_message_element *el;
     233
     234                ret = ldb_msg_add_empty(msg, LTDB_IDX, LDB_FLAG_MOD_ADD, &el);
     235                if (ret != LDB_SUCCESS) {
     236                        talloc_free(msg);
     237                        return ldb_module_oom(module);
     238                }
     239                el->values = list->dn;
     240                el->num_values = list->count;
     241        }
     242
     243        ret = ltdb_store(module, msg, TDB_REPLACE);
    273244        talloc_free(msg);
    274245        return ret;
    275246}
    276247
     248/*
     249  save a dn_list into the database, in either @IDX or internal format
     250 */
     251static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
     252                              struct dn_list *list)
     253{
     254        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     255        TDB_DATA rec, key;
     256        int ret;
     257        struct dn_list *list2;
     258
     259        if (ltdb->idxptr == NULL) {
     260                return ltdb_dn_list_store_full(module, dn, list);
     261        }
     262
     263        if (ltdb->idxptr->itdb == NULL) {
     264                ltdb->idxptr->itdb = tdb_open(NULL, 1000, TDB_INTERNAL, O_RDWR, 0);
     265                if (ltdb->idxptr->itdb == NULL) {
     266                        return LDB_ERR_OPERATIONS_ERROR;
     267                }
     268        }
     269
     270        key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
     271        key.dsize = strlen((char *)key.dptr);
     272
     273        rec = tdb_fetch(ltdb->idxptr->itdb, key);
     274        if (rec.dptr != NULL) {
     275                list2 = ltdb_index_idxptr(module, rec, false);
     276                if (list2 == NULL) {
     277                        free(rec.dptr);
     278                        return LDB_ERR_OPERATIONS_ERROR;
     279                }
     280                free(rec.dptr);
     281                list2->dn = talloc_steal(list2, list->dn);
     282                list2->count = list->count;
     283                return LDB_SUCCESS;
     284        }
     285
     286        list2 = talloc(ltdb->idxptr, struct dn_list);
     287        if (list2 == NULL) {
     288                return LDB_ERR_OPERATIONS_ERROR;
     289        }
     290        list2->dn = talloc_steal(list2, list->dn);
     291        list2->count = list->count;
     292
     293        rec.dptr = (uint8_t *)&list2;
     294        rec.dsize = sizeof(void *);
     295
     296        ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT);
     297        if (ret == -1) {
     298                return ltdb_err_map(tdb_error(ltdb->idxptr->itdb));
     299        }
     300        return LDB_SUCCESS;
     301}
     302
     303/*
     304  traverse function for storing the in-memory index entries on disk
     305 */
     306static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
     307{
     308        struct ldb_module *module = state;
     309        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     310        struct ldb_dn *dn;
     311        struct ldb_context *ldb = ldb_module_get_ctx(module);
     312        struct ldb_val v;
     313        struct dn_list *list;
     314
     315        list = ltdb_index_idxptr(module, data, true);
     316        if (list == NULL) {
     317                ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
     318                return -1;
     319        }
     320
     321        v.data = key.dptr;
     322        v.length = strnlen((char *)key.dptr, key.dsize);
     323
     324        dn = ldb_dn_from_ldb_val(module, ldb, &v);
     325        if (dn == NULL) {
     326                ldb_asprintf_errstring(ldb, "Failed to parse index key %*.*s as an LDB DN", (int)v.length, (int)v.length, (const char *)v.data);
     327                ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
     328                return -1;
     329        }
     330
     331        ltdb->idxptr->error = ltdb_dn_list_store_full(module, dn, list);
     332        talloc_free(dn);
     333        if (ltdb->idxptr->error != 0) {
     334                return -1;
     335        }
     336        return 0;
     337}
     338
    277339/* cleanup the idxptr mode when transaction commits */
    278340int ltdb_index_transaction_commit(struct ldb_module *module)
    279341{
    280         int i;
    281         void *data = ldb_module_get_private(module);
    282         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    283 
    284         /* fix all the DNs that we have modified */
    285         if (ltdb->idxptr) {
    286                 for (i=0;i<ltdb->idxptr->num_dns;i++) {
    287                         ltdb_idxptr_fix_dn(module, ltdb->idxptr->dn_list[i]);
    288                 }
    289 
    290                 if (ltdb->idxptr->repack) {
    291                         tdb_repack(ltdb->tdb);
    292                 }
    293         }
    294 
     342        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     343        int ret;
     344
     345        struct ldb_context *ldb = ldb_module_get_ctx(module);
     346
     347        ldb_reset_err_string(ldb);
     348
     349        if (ltdb->idxptr->itdb) {
     350                tdb_traverse(ltdb->idxptr->itdb, ltdb_index_traverse_store, module);
     351                tdb_close(ltdb->idxptr->itdb);
     352        }
     353
     354        ret = ltdb->idxptr->error;
     355        if (ret != LDB_SUCCESS) {
     356                if (!ldb_errstring(ldb)) {
     357                        ldb_set_errstring(ldb, ldb_strerror(ret));
     358                }
     359                ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb));
     360        }
     361
     362        talloc_free(ltdb->idxptr);
     363        ltdb->idxptr = NULL;
     364        return ret;
     365}
     366
     367/* cleanup the idxptr mode when transaction cancels */
     368int ltdb_index_transaction_cancel(struct ldb_module *module)
     369{
     370        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     371        if (ltdb->idxptr && ltdb->idxptr->itdb) {
     372                tdb_close(ltdb->idxptr->itdb);
     373        }
    295374        talloc_free(ltdb->idxptr);
    296375        ltdb->idxptr = NULL;
     
    298377}
    299378
    300 /* cleanup the idxptr mode when transaction cancels */
    301 int ltdb_index_transaction_cancel(struct ldb_module *module)
    302 {
    303         void *data = ldb_module_get_private(module);
    304         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    305         talloc_free(ltdb->idxptr);
    306         ltdb->idxptr = NULL;
    307         return LDB_SUCCESS;
    308 }
    309 
    310 
    311 
    312 /* a wrapper around ltdb_store() for the index code which
    313    stores in IDXPTR format when idxptr mode is enabled
    314 
    315    WARNING: This modifies the msg which is passed in
    316 */
    317 int ltdb_store_idxptr(struct ldb_module *module, const struct ldb_message *msg, int flgs)
    318 {
    319         void *data = ldb_module_get_private(module);
    320         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    321         int ret;
    322 
    323         if (ltdb->idxptr) {
    324                 int i;
    325                 struct ldb_message *msg2 = ldb_msg_new(module);
    326 
    327                 /* free any old pointer */
    328                 ret = ltdb_search_dn1(module, msg->dn, msg2);
    329                 if (ret == 0) {
    330                         for (i=0;i<msg2->num_elements;i++) {
    331                                 struct ldb_message_element *el = &msg2->elements[i];
    332                                 if (strcmp(el->name, LTDB_IDXPTR) == 0) {
    333                                         ret = ltdb_free_idxptr(module, el);
    334                                         if (ret != LDB_SUCCESS) {
    335                                                 return ret;
    336                                         }
    337                                 }
    338                         }
    339                 }
    340                 talloc_free(msg2);
    341 
    342                 for (i=0;i<msg->num_elements;i++) {
    343                         struct ldb_message_element *el = &msg->elements[i];
    344                         if (strcmp(el->name, LTDB_IDX) == 0) {
    345                                 ret = ltdb_convert_to_idxptr(module, el);
    346                                 if (ret != LDB_SUCCESS) {
    347                                         return ret;
    348                                 }
    349                         }
    350                 }
    351 
    352                 if (ltdb_idxptr_add(module, msg) != 0) {
    353                         return LDB_ERR_OPERATIONS_ERROR;
    354                 }
    355         }
    356 
    357         ret = ltdb_store(module, msg, flgs);
    358         return ret;
    359 }
    360 
    361 
    362 /*
    363   find an element in a list, using the given comparison function and
    364   assuming that the list is already sorted using comp_fn
    365 
    366   return -1 if not found, or the index of the first occurance of needle if found
    367 */
    368 static int ldb_list_find(const void *needle,
    369                          const void *base, size_t nmemb, size_t size,
    370                          comparison_fn_t comp_fn)
    371 {
    372         const char *base_p = (const char *)base;
    373         size_t min_i, max_i, test_i;
    374 
    375         if (nmemb == 0) {
    376                 return -1;
    377         }
    378 
    379         min_i = 0;
    380         max_i = nmemb-1;
    381 
    382         while (min_i < max_i) {
    383                 int r;
    384 
    385                 test_i = (min_i + max_i) / 2;
    386                 /* the following cast looks strange, but is
    387                  correct. The key to understanding it is that base_p
    388                  is a pointer to an array of pointers, so we have to
    389                  dereference it after casting to void **. The strange
    390                  const in the middle gives us the right type of pointer
    391                  after the dereference  (tridge) */
    392                 r = comp_fn(needle, *(void * const *)(base_p + (size * test_i)));
    393                 if (r == 0) {
    394                         /* scan back for first element */
    395                         while (test_i > 0 &&
    396                                comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) {
    397                                 test_i--;
    398                         }
    399                         return test_i;
    400                 }
    401                 if (r < 0) {
    402                         if (test_i == 0) {
    403                                 return -1;
    404                         }
    405                         max_i = test_i - 1;
    406                 }
    407                 if (r > 0) {
    408                         min_i = test_i + 1;
    409                 }
    410         }
    411 
    412         if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) {
    413                 return min_i;
    414         }
    415 
    416         return -1;
    417 }
    418 
    419 struct dn_list {
    420         unsigned int count;
    421         char **dn;
    422 };
    423379
    424380/*
    425381  return the dn key to be used for an index
    426   caller frees
     382  the caller is responsible for freeing
    427383*/
    428384static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
     
    458414        if (ldb_should_b64_encode(ldb, &v)) {
    459415                char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
    460                 if (!vstr) return NULL;
     416                if (!vstr) {
     417                        talloc_free(attr_folded);
     418                        return NULL;
     419                }
    461420                ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
    462421                talloc_free(vstr);
     
    476435  see if a attribute value is in the list of indexed attributes
    477436*/
    478 static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr,
    479                             unsigned int *v_idx, const char *key)
    480 {
    481         unsigned int i, j;
    482         for (i=0;i<msg->num_elements;i++) {
    483                 if (ldb_attr_cmp(msg->elements[i].name, key) == 0) {
    484                         const struct ldb_message_element *el = &msg->elements[i];
    485 
    486                         if (attr == NULL) {
    487                                 /* in this case we are just looking to see if key is present,
    488                                    we are not spearching for a specific index */
    489                                 return 0;
    490                         }
    491 
    492                         for (j=0;j<el->num_values;j++) {
    493                                 if (ldb_attr_cmp((char *)el->values[j].data, attr) == 0) {
    494                                         if (v_idx) {
    495                                                 *v_idx = j;
    496                                         }
    497                                         return i;
    498                                 }
    499                         }
    500                 }
    501         }
    502         return -1;
    503 }
    504 
    505 /* used in sorting dn lists */
    506 static int list_cmp(const char **s1, const char **s2)
    507 {
    508         return strcmp(*s1, *s2);
    509 }
    510 
    511 /*
    512   return a list of dn's that might match a simple indexed search or
     437static bool ltdb_is_indexed(const struct ldb_message *index_list, const char *attr)
     438{
     439        unsigned int i;
     440        struct ldb_message_element *el;
     441
     442        el = ldb_msg_find_element(index_list, LTDB_IDXATTR);
     443        if (el == NULL) {
     444                return false;
     445        }
     446
     447        /* TODO: this is too expensive! At least use a binary search */
     448        for (i=0; i<el->num_values; i++) {
     449                if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) {
     450                        return true;
     451                }
     452        }
     453        return false;
     454}
     455
     456/*
     457  in the following logic functions, the return value is treated as
     458  follows:
     459
     460     LDB_SUCCESS: we found some matching index values
     461
     462     LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
     463
     464     LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
     465                               we'll need a full search
     466 */
     467
     468/*
     469  return a list of dn's that might match a simple indexed search (an
     470  equality search only)
    513471 */
    514472static int ltdb_index_dn_simple(struct ldb_module *module,
     
    520478        struct ldb_dn *dn;
    521479        int ret;
    522         unsigned int i, j;
    523         struct ldb_message *msg;
    524480
    525481        ldb = ldb_module_get_ctx(module);
     
    530486        /* if the attribute isn't in the list of indexed attributes then
    531487           this node needs a full search */
    532         if (ldb_msg_find_idx(index_list, tree->u.equality.attr, NULL, LTDB_IDXATTR) == -1) {
     488        if (!ltdb_is_indexed(index_list, tree->u.equality.attr)) {
    533489                return LDB_ERR_OPERATIONS_ERROR;
    534490        }
     
    539495        if (!dn) return LDB_ERR_OPERATIONS_ERROR;
    540496
    541         msg = talloc(list, struct ldb_message);
    542         if (msg == NULL) {
    543                 return LDB_ERR_OPERATIONS_ERROR;
    544         }
    545 
    546         ret = ltdb_search_dn1_index(module, dn, msg);
     497        ret = ltdb_dn_list_load(module, dn, list);
    547498        talloc_free(dn);
    548         if (ret != LDB_SUCCESS) {
    549                 return ret;
    550         }
    551 
    552         for (i=0;i<msg->num_elements;i++) {
    553                 struct ldb_message_element *el;
    554 
    555                 if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
    556                         continue;
    557                 }
    558 
    559                 el = &msg->elements[i];
    560 
    561                 list->dn = talloc_array(list, char *, el->num_values);
    562                 if (!list->dn) {
    563                         talloc_free(msg);
    564                         return LDB_ERR_OPERATIONS_ERROR;
    565                 }
    566 
    567                 for (j=0;j<el->num_values;j++) {
    568                         list->dn[list->count] =
    569                                 talloc_strdup(list->dn, (char *)el->values[j].data);
    570                         if (!list->dn[list->count]) {
    571                                 talloc_free(msg);
    572                                 return LDB_ERR_OPERATIONS_ERROR;
    573                         }
    574                         list->count++;
    575                 }
    576         }
    577 
    578         talloc_free(msg);
    579 
    580         if (list->count > 1) {
    581                 qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp);
    582         }
    583 
    584         return LDB_SUCCESS;
    585 }
    586 
    587 
    588 static int list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
     499        return ret;
     500}
     501
     502
     503static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
    589504
    590505/*
     
    596511                              struct dn_list *list)
    597512{
    598         struct ldb_context *ldb;
    599         ldb = ldb_module_get_ctx(module);
    600 
    601513        if (ldb_attr_dn(tree->u.equality.attr) == 0) {
    602                 list->dn = talloc_array(list, char *, 1);
     514                list->dn = talloc_array(list, struct ldb_val, 1);
    603515                if (list->dn == NULL) {
    604                         ldb_oom(ldb);
     516                        ldb_module_oom(module);
    605517                        return LDB_ERR_OPERATIONS_ERROR;
    606518                }
    607                 list->dn[0] = talloc_strdup(list->dn, (char *)tree->u.equality.value.data);
    608                 if (list->dn[0] == NULL) {
    609                         ldb_oom(ldb);
    610                         return LDB_ERR_OPERATIONS_ERROR;
    611                 }
     519                list->dn[0] = tree->u.equality.value;
    612520                list->count = 1;
    613521                return LDB_SUCCESS;
     
    620528  list intersection
    621529  list = list & list2
    622   relies on the lists being sorted
    623 */
    624 static int list_intersect(struct ldb_context *ldb,
    625                           struct dn_list *list, const struct dn_list *list2)
     530*/
     531static bool list_intersect(struct ldb_context *ldb,
     532                           struct dn_list *list, const struct dn_list *list2)
    626533{
    627534        struct dn_list *list3;
    628535        unsigned int i;
    629536
    630         if (list->count == 0 || list2->count == 0) {
     537        if (list->count == 0) {
    631538                /* 0 & X == 0 */
    632                 return LDB_ERR_NO_SUCH_OBJECT;
    633         }
    634 
    635         list3 = talloc(ldb, struct dn_list);
     539                return true;
     540        }
     541        if (list2->count == 0) {
     542                /* X & 0 == 0 */
     543                list->count = 0;
     544                list->dn = NULL;
     545                return true;
     546        }
     547
     548        /* the indexing code is allowed to return a longer list than
     549           what really matches, as all results are filtered by the
     550           full expression at the end - this shortcut avoids a lot of
     551           work in some cases */
     552        if (list->count < 2 && list2->count > 10) {
     553                return true;
     554        }
     555        if (list2->count < 2 && list->count > 10) {
     556                list->count = list2->count;
     557                list->dn = list2->dn;
     558                /* note that list2 may not be the parent of list2->dn,
     559                   as list2->dn may be owned by ltdb->idxptr. In that
     560                   case we expect this reparent call to fail, which is
     561                   OK */
     562                talloc_reparent(list2, list, list2->dn);
     563                return true;
     564        }
     565
     566        list3 = talloc_zero(list, struct dn_list);
    636567        if (list3 == NULL) {
    637                 return LDB_ERR_OPERATIONS_ERROR;
    638         }
    639 
    640         list3->dn = talloc_array(list3, char *, list->count);
     568                return false;
     569        }
     570
     571        list3->dn = talloc_array(list3, struct ldb_val, list->count);
    641572        if (!list3->dn) {
    642573                talloc_free(list3);
    643                 return LDB_ERR_OPERATIONS_ERROR;
     574                return false;
    644575        }
    645576        list3->count = 0;
    646577
    647578        for (i=0;i<list->count;i++) {
    648                 if (ldb_list_find(list->dn[i], list2->dn, list2->count,
    649                               sizeof(char *), (comparison_fn_t)strcmp) != -1) {
    650                         list3->dn[list3->count] = talloc_move(list3->dn, &list->dn[i]);
     579                if (ltdb_dn_list_find_val(list2, &list->dn[i]) != -1) {
     580                        list3->dn[list3->count] = list->dn[i];
    651581                        list3->count++;
    652                 } else {
    653                         talloc_free(list->dn[i]);
    654                 }
    655         }
    656 
    657         talloc_free(list->dn);
    658         list->dn = talloc_move(list, &list3->dn);
     582                }
     583        }
     584
     585        list->dn = talloc_steal(list, list3->dn);
    659586        list->count = list3->count;
    660587        talloc_free(list3);
    661588
    662         return LDB_ERR_NO_SUCH_OBJECT;
     589        return true;
    663590}
    664591
     
    667594  list union
    668595  list = list | list2
    669   relies on the lists being sorted
    670 */
    671 static int list_union(struct ldb_context *ldb,
    672                       struct dn_list *list, const struct dn_list *list2)
    673 {
    674         unsigned int i;
    675         char **d;
    676         unsigned int count = list->count;
    677 
    678         if (list->count == 0 && list2->count == 0) {
    679                 /* 0 | 0 == 0 */
    680                 return LDB_ERR_NO_SUCH_OBJECT;
    681         }
    682 
    683         d = talloc_realloc(list, list->dn, char *, list->count + list2->count);
    684         if (!d) {
    685                 return LDB_ERR_OPERATIONS_ERROR;
    686         }
    687         list->dn = d;
    688 
    689         for (i=0;i<list2->count;i++) {
    690                 if (ldb_list_find(list2->dn[i], list->dn, count,
    691                               sizeof(char *), (comparison_fn_t)strcmp) == -1) {
    692                         list->dn[list->count] = talloc_strdup(list->dn, list2->dn[i]);
    693                         if (!list->dn[list->count]) {
    694                                 return LDB_ERR_OPERATIONS_ERROR;
    695                         }
    696                         list->count++;
    697                 }
    698         }
    699 
    700         if (list->count != count) {
    701                 qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t)list_cmp);
    702         }
    703 
    704         return LDB_ERR_NO_SUCH_OBJECT;
     596*/
     597static bool list_union(struct ldb_context *ldb,
     598                       struct dn_list *list, const struct dn_list *list2)
     599{
     600        struct ldb_val *dn3;
     601
     602        if (list2->count == 0) {
     603                /* X | 0 == X */
     604                return true;
     605        }
     606
     607        if (list->count == 0) {
     608                /* 0 | X == X */
     609                list->count = list2->count;
     610                list->dn = list2->dn;
     611                /* note that list2 may not be the parent of list2->dn,
     612                   as list2->dn may be owned by ltdb->idxptr. In that
     613                   case we expect this reparent call to fail, which is
     614                   OK */
     615                talloc_reparent(list2, list, list2->dn);
     616                return true;
     617        }
     618
     619        dn3 = talloc_array(list, struct ldb_val, list->count + list2->count);
     620        if (!dn3) {
     621                ldb_oom(ldb);
     622                return false;
     623        }
     624
     625        /* we allow for duplicates here, and get rid of them later */
     626        memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count);
     627        memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count);
     628
     629        list->dn = dn3;
     630        list->count += list2->count;
     631
     632        return true;
    705633}
    706634
     
    712640
    713641/*
    714   OR two index results
     642  process an OR list (a union)
    715643 */
    716644static int ltdb_index_dn_or(struct ldb_module *module,
     
    721649        struct ldb_context *ldb;
    722650        unsigned int i;
    723         int ret;
    724651
    725652        ldb = ldb_module_get_ctx(module);
    726653
    727         ret = LDB_ERR_OPERATIONS_ERROR;
    728654        list->dn = NULL;
    729655        list->count = 0;
    730656
    731         for (i=0;i<tree->u.list.num_elements;i++) {
     657        for (i=0; i<tree->u.list.num_elements; i++) {
    732658                struct dn_list *list2;
    733                 int v;
    734 
    735                 list2 = talloc(module, struct dn_list);
     659                int ret;
     660
     661                list2 = talloc_zero(list, struct dn_list);
    736662                if (list2 == NULL) {
    737663                        return LDB_ERR_OPERATIONS_ERROR;
    738664                }
    739665
    740                 v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
    741 
    742                 if (v == LDB_ERR_NO_SUCH_OBJECT) {
    743                         /* 0 || X == X */
    744                         if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
    745                                 ret = v;
    746                         }
     666                ret = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
     667
     668                if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     669                        /* X || 0 == X */
    747670                        talloc_free(list2);
    748671                        continue;
    749672                }
    750673
    751                 if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
    752                         /* 1 || X == 1 */
    753                         talloc_free(list->dn);
     674                if (ret != LDB_SUCCESS) {
     675                        /* X || * == * */
    754676                        talloc_free(list2);
    755                         return v;
    756                 }
    757 
    758                 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
    759                         ret = LDB_SUCCESS;
    760                         list->dn = talloc_move(list, &list2->dn);
    761                         list->count = list2->count;
    762                 } else {
    763                         if (list_union(ldb, list, list2) == -1) {
    764                                 talloc_free(list2);
    765                                 return LDB_ERR_OPERATIONS_ERROR;
    766                         }
    767                         ret = LDB_SUCCESS;
    768                 }
    769                 talloc_free(list2);
     677                        return ret;
     678                }
     679
     680                if (!list_union(ldb, list, list2)) {
     681                        talloc_free(list2);
     682                        return LDB_ERR_OPERATIONS_ERROR;
     683                }
    770684        }
    771685
     
    774688        }
    775689
    776         return ret;
     690        return LDB_SUCCESS;
    777691}
    778692
     
    810724
    811725/*
    812   AND two index results
     726  process an AND expression (intersection)
    813727 */
    814728static int ltdb_index_dn_and(struct ldb_module *module,
     
    819733        struct ldb_context *ldb;
    820734        unsigned int i;
    821         int ret, pass;
     735        bool found;
    822736
    823737        ldb = ldb_module_get_ctx(module);
    824738
    825         ret = LDB_ERR_OPERATIONS_ERROR;
    826739        list->dn = NULL;
    827740        list->count = 0;
    828741
    829         for (pass=0;pass<=1;pass++) {
    830                 /* in the first pass we only look for unique simple
    831                    equality tests, in the hope of avoiding having to look
    832                    at any others */
    833                 bool only_unique = pass==0?true:false;
    834 
    835                 for (i=0;i<tree->u.list.num_elements;i++) {
    836                         struct dn_list *list2;
    837                         int v;
    838                         bool is_unique = false;
    839                         const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
    840 
    841                         if (subtree->operation == LDB_OP_EQUALITY &&
    842                             ltdb_index_unique(ldb, subtree->u.equality.attr)) {
    843                                 is_unique = true;
    844                         }
    845                         if (is_unique != only_unique) continue;
     742        /* in the first pass we only look for unique simple
     743           equality tests, in the hope of avoiding having to look
     744           at any others */
     745        for (i=0; i<tree->u.list.num_elements; i++) {
     746                const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
     747                int ret;
     748
     749                if (subtree->operation != LDB_OP_EQUALITY ||
     750                    !ltdb_index_unique(ldb, subtree->u.equality.attr)) {
     751                        continue;
     752                }
     753               
     754                ret = ltdb_index_dn(module, subtree, index_list, list);
     755                if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     756                        /* 0 && X == 0 */
     757                        return LDB_ERR_NO_SUCH_OBJECT;
     758                }
     759                if (ret == LDB_SUCCESS) {
     760                        /* a unique index match means we can
     761                         * stop. Note that we don't care if we return
     762                         * a few too many objects, due to later
     763                         * filtering */
     764                        return LDB_SUCCESS;
     765                }
     766        }       
     767
     768        /* now do a full intersection */
     769        found = false;
     770
     771        for (i=0; i<tree->u.list.num_elements; i++) {
     772                const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
     773                struct dn_list *list2;
     774                int ret;
     775
     776                list2 = talloc_zero(list, struct dn_list);
     777                if (list2 == NULL) {
     778                        return ldb_module_oom(module);
     779                }
    846780                       
    847                         list2 = talloc(module, struct dn_list);
    848                         if (list2 == NULL) {
    849                                 return LDB_ERR_OPERATIONS_ERROR;
    850                         }
     781                ret = ltdb_index_dn(module, subtree, index_list, list2);
     782
     783                if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     784                        /* X && 0 == 0 */
     785                        list->dn = NULL;
     786                        list->count = 0;
     787                        talloc_free(list2);
     788                        return LDB_ERR_NO_SUCH_OBJECT;
     789                }
     790               
     791                if (ret != LDB_SUCCESS) {
     792                        /* this didn't adding anything */
     793                        talloc_free(list2);
     794                        continue;
     795                }
     796
     797                if (!found) {
     798                        talloc_reparent(list2, list, list->dn);
     799                        list->dn = list2->dn;
     800                        list->count = list2->count;
     801                        found = true;
     802                } else if (!list_intersect(ldb, list, list2)) {
     803                        talloc_free(list2);
     804                        return LDB_ERR_OPERATIONS_ERROR;
     805                }
    851806                       
    852                         v = ltdb_index_dn(module, subtree, index_list, list2);
    853 
    854                         if (v == LDB_ERR_NO_SUCH_OBJECT) {
    855                                 /* 0 && X == 0 */
    856                                 talloc_free(list->dn);
    857                                 talloc_free(list2);
    858                                 return LDB_ERR_NO_SUCH_OBJECT;
    859                         }
     807                if (list->count == 0) {
     808                        list->dn = NULL;
     809                        return LDB_ERR_NO_SUCH_OBJECT;
     810                }
    860811                       
    861                         if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
    862                                 talloc_free(list2);
    863                                 continue;
    864                         }
    865                        
    866                         if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
    867                                 ret = LDB_SUCCESS;
    868                                 talloc_free(list->dn);
    869                                 list->dn = talloc_move(list, &list2->dn);
    870                                 list->count = list2->count;
    871                         } else {
    872                                 if (list_intersect(ldb, list, list2) == -1) {
    873                                         talloc_free(list2);
    874                                         return LDB_ERR_OPERATIONS_ERROR;
    875                                 }
    876                         }
    877                        
    878                         talloc_free(list2);
    879                        
    880                         if (list->count == 0) {
    881                                 talloc_free(list->dn);
    882                                 return LDB_ERR_NO_SUCH_OBJECT;
    883                         }
    884                        
    885                         if (list->count == 1) {
    886                                 /* it isn't worth loading the next part of the tree */
    887                                 return ret;
    888                         }
     812                if (list->count < 2) {
     813                        /* it isn't worth loading the next part of the tree */
     814                        return LDB_SUCCESS;
    889815                }
    890816        }       
    891         return ret;
     817
     818        if (!found) {
     819                /* none of the attributes were indexed */
     820                return LDB_ERR_OPERATIONS_ERROR;
     821        }
     822
     823        return LDB_SUCCESS;
    892824}
    893825       
    894826/*
    895   AND index results and ONE level special index
     827  return a list of matching objects using a one-level index
    896828 */
    897829static int ltdb_index_dn_one(struct ldb_module *module,
     
    900832{
    901833        struct ldb_context *ldb;
    902         struct dn_list *list2;
    903         struct ldb_message *msg;
    904834        struct ldb_dn *key;
    905835        struct ldb_val val;
    906         unsigned int i, j;
    907836        int ret;
    908837
    909838        ldb = ldb_module_get_ctx(module);
    910839
    911         list2 = talloc_zero(module, struct dn_list);
    912         if (list2 == NULL) {
    913                 return LDB_ERR_OPERATIONS_ERROR;
    914         }
    915 
    916         /* the attribute is indexed. Pull the list of DNs that match the
    917            search criterion */
     840        /* work out the index key from the parent DN */
    918841        val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
    919842        val.length = strlen((char *)val.data);
    920843        key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
    921844        if (!key) {
    922                 talloc_free(list2);
    923                 return LDB_ERR_OPERATIONS_ERROR;
    924         }
    925 
    926         msg = talloc(list2, struct ldb_message);
    927         if (msg == NULL) {
    928                 talloc_free(list2);
    929                 return LDB_ERR_OPERATIONS_ERROR;
    930         }
    931 
    932         ret = ltdb_search_dn1_index(module, key, msg);
     845                ldb_oom(ldb);
     846                return LDB_ERR_OPERATIONS_ERROR;
     847        }
     848
     849        ret = ltdb_dn_list_load(module, key, list);
    933850        talloc_free(key);
    934851        if (ret != LDB_SUCCESS) {
     
    936853        }
    937854
    938         for (i = 0; i < msg->num_elements; i++) {
    939                 struct ldb_message_element *el;
    940 
    941                 if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
    942                         continue;
    943                 }
    944 
    945                 el = &msg->elements[i];
    946 
    947                 list2->dn = talloc_array(list2, char *, el->num_values);
    948                 if (!list2->dn) {
    949                         talloc_free(list2);
    950                         return LDB_ERR_OPERATIONS_ERROR;
    951                 }
    952 
    953                 for (j = 0; j < el->num_values; j++) {
    954                         list2->dn[list2->count] = talloc_strdup(list2->dn, (char *)el->values[j].data);
    955                         if (!list2->dn[list2->count]) {
    956                                 talloc_free(list2);
    957                                 return LDB_ERR_OPERATIONS_ERROR;
    958                         }
    959                         list2->count++;
    960                 }
    961         }
    962 
    963         if (list2->count == 0) {
    964                 talloc_free(list2);
     855        if (list->count == 0) {
    965856                return LDB_ERR_NO_SUCH_OBJECT;
    966857        }
    967 
    968         if (list2->count > 1) {
    969                 qsort(list2->dn, list2->count, sizeof(char *), (comparison_fn_t) list_cmp);
    970         }
    971 
    972         if (list->count > 0) {
    973                 if (list_intersect(ldb, list, list2) == -1) {
    974                         talloc_free(list2);
    975                         return LDB_ERR_OPERATIONS_ERROR;
    976                 }
    977 
    978                 if (list->count == 0) {
    979                         talloc_free(list->dn);
    980                         talloc_free(list2);
    981                         return LDB_ERR_NO_SUCH_OBJECT;
    982                 }
    983         } else {
    984                 list->dn = talloc_move(list, &list2->dn);
    985                 list->count = list2->count;
    986         }
    987 
    988         talloc_free(list2);
    989858
    990859        return LDB_SUCCESS;
     
    1050919                struct ldb_dn *dn;
    1051920                int ret;
     921                bool matched;
    1052922
    1053923                msg = ldb_msg_new(ac);
     
    1056926                }
    1057927
    1058                 dn = ldb_dn_new(msg, ldb, dn_list->dn[i]);
     928                dn = ldb_dn_from_ldb_val(msg, ldb, &dn_list->dn[i]);
    1059929                if (dn == NULL) {
    1060930                        talloc_free(msg);
     
    1076946                }
    1077947
    1078                 if (!ldb_match_msg(ldb, msg,
    1079                                    ac->tree, ac->base, ac->scope)) {
     948                ret = ldb_match_msg_error(ldb, msg,
     949                                          ac->tree, ac->base, ac->scope, &matched);
     950                if (ret != LDB_SUCCESS) {
     951                        talloc_free(msg);
     952                        return ret;
     953                }
     954                if (!matched) {
    1080955                        talloc_free(msg);
    1081956                        continue;
     
    1092967                ret = ldb_module_send_entry(ac->req, msg, NULL);
    1093968                if (ret != LDB_SUCCESS) {
     969                        /* Regardless of success or failure, the msg
     970                         * is the callbacks responsiblity, and should
     971                         * not be talloc_free()'ed */
    1094972                        ac->request_terminated = true;
    1095973                        return ret;
     
    1100978
    1101979        return LDB_SUCCESS;
     980}
     981
     982/*
     983  remove any duplicated entries in a indexed result
     984 */
     985static void ltdb_dn_list_remove_duplicates(struct dn_list *list)
     986{
     987        unsigned int i, new_count;
     988
     989        if (list->count < 2) {
     990                return;
     991        }
     992
     993        TYPESAFE_QSORT(list->dn, list->count, dn_list_cmp);
     994
     995        new_count = 1;
     996        for (i=1; i<list->count; i++) {
     997                if (dn_list_cmp(&list->dn[i], &list->dn[new_count-1]) != 0) {
     998                        if (new_count != i) {
     999                                list->dn[new_count] = list->dn[i];
     1000                        }
     1001                        new_count++;
     1002                }
     1003        }
     1004       
     1005        list->count = new_count;
    11021006}
    11031007
     
    11091013int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
    11101014{
    1111         struct ldb_context *ldb;
    1112         void *data = ldb_module_get_private(ac->module);
    1113         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
     1015        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private);
    11141016        struct dn_list *dn_list;
    1115         int ret, idxattr, idxone;
    1116 
    1117         ldb = ldb_module_get_ctx(ac->module);
    1118 
    1119         idxattr = idxone = 0;
    1120         ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXATTR);
    1121         if (ret == 0 ) {
    1122                 idxattr = 1;
    1123         }
    1124 
    1125         /* We do one level indexing only if requested */
    1126         ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
    1127         if (ret == 0 ) {
    1128                 idxone = 1;
    1129         }
    1130 
    1131         if ((ac->scope == LDB_SCOPE_ONELEVEL && (idxattr+idxone == 0)) ||
    1132             (ac->scope == LDB_SCOPE_SUBTREE && idxattr == 0)) {
    1133                 /* no indexes? must do full search */
    1134                 return LDB_ERR_OPERATIONS_ERROR;
    1135         }
    1136 
    1137         ret = LDB_ERR_OPERATIONS_ERROR;
     1017        int ret;
     1018
     1019        /* see if indexing is enabled */
     1020        if (!ltdb->cache->attribute_indexes &&
     1021            !ltdb->cache->one_level_indexes &&
     1022            ac->scope != LDB_SCOPE_BASE) {
     1023                /* fallback to a full search */
     1024                return LDB_ERR_OPERATIONS_ERROR;
     1025        }
    11381026
    11391027        dn_list = talloc_zero(ac, struct dn_list);
    11401028        if (dn_list == NULL) {
    1141                 return LDB_ERR_OPERATIONS_ERROR;
    1142         }
    1143 
    1144         if (ac->scope == LDB_SCOPE_BASE) {
    1145                 /* with BASE searches only one DN can match */
    1146                 dn_list->dn = talloc_array(dn_list, char *, 1);
     1029                return ldb_module_oom(ac->module);
     1030        }
     1031
     1032        switch (ac->scope) {
     1033        case LDB_SCOPE_BASE:
     1034                dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
    11471035                if (dn_list->dn == NULL) {
    1148                         ldb_oom(ldb);
     1036                        talloc_free(dn_list);
     1037                        return ldb_module_oom(ac->module);
     1038                }
     1039                dn_list->dn[0].data = discard_const_p(unsigned char, ldb_dn_get_linearized(ac->base));
     1040                if (dn_list->dn[0].data == NULL) {
     1041                        talloc_free(dn_list);
     1042                        return ldb_module_oom(ac->module);
     1043                }
     1044                dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
     1045                dn_list->count = 1;
     1046                break;         
     1047
     1048        case LDB_SCOPE_ONELEVEL:
     1049                if (!ltdb->cache->one_level_indexes) {
     1050                        talloc_free(dn_list);
    11491051                        return LDB_ERR_OPERATIONS_ERROR;
    11501052                }
    1151                 dn_list->dn[0] = ldb_dn_alloc_linearized(dn_list, ac->base);
    1152                 if (dn_list->dn[0] == NULL) {
    1153                         ldb_oom(ldb);
     1053                ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
     1054                if (ret != LDB_SUCCESS) {
     1055                        talloc_free(dn_list);
     1056                        return ret;
     1057                }
     1058                break;
     1059
     1060        case LDB_SCOPE_SUBTREE:
     1061        case LDB_SCOPE_DEFAULT:
     1062                if (!ltdb->cache->attribute_indexes) {
     1063                        talloc_free(dn_list);
    11541064                        return LDB_ERR_OPERATIONS_ERROR;
    11551065                }
    1156                 dn_list->count = 1;
    1157                 ret = LDB_SUCCESS;
    1158         }
    1159 
    1160         if (ac->scope != LDB_SCOPE_BASE && idxattr == 1) {
    11611066                ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
    1162         }
    1163 
    1164         if (ret == LDB_ERR_OPERATIONS_ERROR &&
    1165             ac->scope == LDB_SCOPE_ONELEVEL && idxone == 1) {
    1166                 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
    1167         }
    1168 
    1169         if (ret == LDB_SUCCESS) {
    1170                 /* we've got a candidate list - now filter by the full tree
    1171                    and extract the needed attributes */
    1172                 ret = ltdb_index_filter(dn_list, ac, match_count);
    1173         }
    1174 
     1067                if (ret != LDB_SUCCESS) {
     1068                        talloc_free(dn_list);
     1069                        return ret;
     1070                }
     1071                ltdb_dn_list_remove_duplicates(dn_list);
     1072                break;
     1073        }
     1074
     1075        ret = ltdb_index_filter(dn_list, ac, match_count);
    11751076        talloc_free(dn_list);
    1176 
    11771077        return ret;
    1178 }
    1179 
    1180 /*
    1181   add a index element where this is the first indexed DN for this value
    1182 */
    1183 static int ltdb_index_add1_new(struct ldb_context *ldb,
    1184                                struct ldb_message *msg,
    1185                                const char *dn)
    1186 {
    1187         struct ldb_message_element *el;
    1188 
    1189         /* add another entry */
    1190         el = talloc_realloc(msg, msg->elements,
    1191                                struct ldb_message_element, msg->num_elements+1);
    1192         if (!el) {
    1193                 return LDB_ERR_OPERATIONS_ERROR;
    1194         }
    1195 
    1196         msg->elements = el;
    1197         msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, LTDB_IDX);
    1198         if (!msg->elements[msg->num_elements].name) {
    1199                 return LDB_ERR_OPERATIONS_ERROR;
    1200         }
    1201         msg->elements[msg->num_elements].num_values = 0;
    1202         msg->elements[msg->num_elements].values = talloc(msg->elements, struct ldb_val);
    1203         if (!msg->elements[msg->num_elements].values) {
    1204                 return LDB_ERR_OPERATIONS_ERROR;
    1205         }
    1206         msg->elements[msg->num_elements].values[0].length = strlen(dn);
    1207         msg->elements[msg->num_elements].values[0].data = discard_const_p(uint8_t, dn);
    1208         msg->elements[msg->num_elements].num_values = 1;
    1209         msg->num_elements++;
    1210 
    1211         return LDB_SUCCESS;
    1212 }
    1213 
    1214 
    1215 /*
    1216   add a index element where this is not the first indexed DN for this
    1217   value
    1218 */
    1219 static int ltdb_index_add1_add(struct ldb_context *ldb,
    1220                                struct ldb_message *msg,
    1221                                int idx,
    1222                                const char *dn,
    1223                                const struct ldb_schema_attribute *a)
    1224 {
    1225         struct ldb_val *v2;
    1226         unsigned int i;
    1227 
    1228         /* for multi-valued attributes we can end up with repeats */
    1229         for (i=0;i<msg->elements[idx].num_values;i++) {
    1230                 if (strcmp(dn, (char *)msg->elements[idx].values[i].data) == 0) {
    1231                         return LDB_SUCCESS;
    1232                 }
    1233         }
    1234 
    1235         if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
    1236                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
    1237         }
    1238 
    1239         v2 = talloc_realloc(msg->elements, msg->elements[idx].values,
    1240                               struct ldb_val,
    1241                               msg->elements[idx].num_values+1);
    1242         if (!v2) {
    1243                 return LDB_ERR_OPERATIONS_ERROR;
    1244         }
    1245         msg->elements[idx].values = v2;
    1246 
    1247         msg->elements[idx].values[msg->elements[idx].num_values].length = strlen(dn);
    1248         msg->elements[idx].values[msg->elements[idx].num_values].data = discard_const_p(uint8_t, dn);
    1249         msg->elements[idx].num_values++;
    1250 
    1251         return LDB_SUCCESS;
    12521078}
    12531079
     
    12591085{
    12601086        struct ldb_context *ldb;
    1261         struct ldb_message *msg;
    12621087        struct ldb_dn *dn_key;
    12631088        int ret;
    1264         unsigned int i;
    12651089        const struct ldb_schema_attribute *a;
     1090        struct dn_list *list;
     1091        unsigned alloc_len;
    12661092
    12671093        ldb = ldb_module_get_ctx(module);
    12681094
    1269         msg = talloc(module, struct ldb_message);
    1270         if (msg == NULL) {
    1271                 errno = ENOMEM;
     1095        list = talloc_zero(module, struct dn_list);
     1096        if (list == NULL) {
    12721097                return LDB_ERR_OPERATIONS_ERROR;
    12731098        }
     
    12751100        dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
    12761101        if (!dn_key) {
    1277                 talloc_free(msg);
    1278                 return LDB_ERR_OPERATIONS_ERROR;
    1279         }
    1280         talloc_steal(msg, dn_key);
    1281 
    1282         ret = ltdb_search_dn1_index(module, dn_key, msg);
     1102                talloc_free(list);
     1103                return LDB_ERR_OPERATIONS_ERROR;
     1104        }
     1105        talloc_steal(list, dn_key);
     1106
     1107        ret = ltdb_dn_list_load(module, dn_key, list);
    12831108        if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
    1284                 talloc_free(msg);
     1109                talloc_free(list);
    12851110                return ret;
    12861111        }
    12871112
    1288         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
    1289                 msg->dn = dn_key;
    1290                 msg->num_elements = 0;
    1291                 msg->elements = NULL;
    1292         }
    1293 
    1294         for (i=0;i<msg->num_elements;i++) {
    1295                 if (strcmp(LTDB_IDX, msg->elements[i].name) == 0) {
    1296                         break;
    1297                 }
    1298         }
    1299 
    1300         if (i == msg->num_elements) {
    1301                 ret = ltdb_index_add1_new(ldb, msg, dn);
    1302         } else {
    1303                 ret = ltdb_index_add1_add(ldb, msg, i, dn, a);
    1304         }
    1305 
    1306         if (ret == LDB_SUCCESS) {
    1307                 ret = ltdb_store_idxptr(module, msg, TDB_REPLACE);
    1308         }
    1309 
    1310         talloc_free(msg);
     1113        if (ltdb_dn_list_find_str(list, dn) != -1) {
     1114                talloc_free(list);
     1115                return LDB_SUCCESS;
     1116        }
     1117
     1118        if (list->count > 0 &&
     1119            a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
     1120                talloc_free(list);
     1121                ldb_asprintf_errstring(ldb, __location__ ": unique index violation on %s in %s",
     1122                                       el->name, dn);
     1123                return LDB_ERR_ENTRY_ALREADY_EXISTS;           
     1124        }
     1125
     1126        /* overallocate the list a bit, to reduce the number of
     1127         * realloc trigered copies */   
     1128        alloc_len = ((list->count+1)+7) & ~7;
     1129        list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len);
     1130        if (list->dn == NULL) {
     1131                talloc_free(list);
     1132                return LDB_ERR_OPERATIONS_ERROR;
     1133        }
     1134        list->dn[list->count].data = (uint8_t *)talloc_strdup(list->dn, dn);
     1135        list->dn[list->count].length = strlen(dn);
     1136        list->count++;
     1137
     1138        ret = ltdb_dn_list_store(module, dn_key, list);
     1139
     1140        talloc_free(list);
    13111141
    13121142        return ret;
    13131143}
    13141144
    1315 static int ltdb_index_add0(struct ldb_module *module, const char *dn,
    1316                            struct ldb_message_element *elements, int num_el)
    1317 {
    1318         void *data = ldb_module_get_private(module);
    1319         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    1320         int ret;
    1321         unsigned int i, j;
     1145/*
     1146  add index entries for one elements in a message
     1147 */
     1148static int ltdb_index_add_el(struct ldb_module *module, const char *dn,
     1149                             struct ldb_message_element *el)
     1150{
     1151        unsigned int i;
     1152        for (i = 0; i < el->num_values; i++) {
     1153                int ret = ltdb_index_add1(module, dn, el, i);
     1154                if (ret != LDB_SUCCESS) {
     1155                        return ret;
     1156                }
     1157        }
     1158
     1159        return LDB_SUCCESS;
     1160}
     1161
     1162/*
     1163  add index entries for all elements in a message
     1164 */
     1165static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
     1166                              struct ldb_message_element *elements, int num_el)
     1167{
     1168        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     1169        unsigned int i;
    13221170
    13231171        if (dn[0] == '@') {
     
    13311179
    13321180        for (i = 0; i < num_el; i++) {
    1333                 ret = ldb_msg_find_idx(ltdb->cache->indexlist, elements[i].name,
    1334                                        NULL, LTDB_IDXATTR);
    1335                 if (ret == -1) {
     1181                int ret;
     1182                if (!ltdb_is_indexed(ltdb->cache->indexlist, elements[i].name)) {
    13361183                        continue;
    13371184                }
    1338                 for (j = 0; j < elements[i].num_values; j++) {
    1339                         ret = ltdb_index_add1(module, dn, &elements[i], j);
    1340                         if (ret != LDB_SUCCESS) {
    1341                                 return ret;
    1342                         }
     1185                ret = ltdb_index_add_el(module, dn, &elements[i]);
     1186                if (ret != LDB_SUCCESS) {
     1187                        struct ldb_context *ldb = ldb_module_get_ctx(module);
     1188                        ldb_asprintf_errstring(ldb,
     1189                                               __location__ ": Failed to re-index %s in %s - %s",
     1190                                               elements[i].name, dn, ldb_errstring(ldb));
     1191                        return ret;
    13431192                }
    13441193        }
     
    13471196}
    13481197
    1349 /*
    1350   add the index entries for a new record
    1351 */
    1352 int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg)
    1353 {
    1354         const char *dn;
    1355         int ret;
    1356 
    1357         dn = ldb_dn_get_linearized(msg->dn);
    1358         if (dn == NULL) {
    1359                 return LDB_ERR_OPERATIONS_ERROR;
    1360         }
    1361 
    1362         ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
    1363 
    1364         return ret;
    1365 }
    1366 
    1367 
    1368 /*
    1369   delete an index entry for one message element
    1370 */
    1371 int ltdb_index_del_value(struct ldb_module *module, const char *dn,
    1372                          struct ldb_message_element *el, int v_idx)
    1373 {
    1374         struct ldb_context *ldb;
    1375         struct ldb_message *msg;
    1376         struct ldb_dn *dn_key;
    1377         int ret, i;
    1378         unsigned int j;
    1379 
    1380         ldb = ldb_module_get_ctx(module);
    1381 
    1382         if (dn[0] == '@') {
    1383                 return LDB_SUCCESS;
    1384         }
    1385 
    1386         dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
    1387         if (!dn_key) {
    1388                 return LDB_ERR_OPERATIONS_ERROR;
    1389         }
    1390 
    1391         msg = talloc(dn_key, struct ldb_message);
    1392         if (msg == NULL) {
    1393                 talloc_free(dn_key);
    1394                 return LDB_ERR_OPERATIONS_ERROR;
    1395         }
    1396 
    1397         ret = ltdb_search_dn1_index(module, dn_key, msg);
    1398         if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
    1399                 talloc_free(dn_key);
    1400                 return ret;
    1401         }
    1402 
    1403         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
    1404                 /* it wasn't indexed. Did we have an earlier error? If we did then
    1405                    its gone now */
    1406                 talloc_free(dn_key);
    1407                 return LDB_SUCCESS;
    1408         }
    1409 
    1410         i = ldb_msg_find_idx(msg, dn, &j, LTDB_IDX);
    1411         if (i == -1) {
    1412                 struct ldb_ldif ldif;
    1413                 char *ldif_string;
    1414                 ldif.changetype = LDB_CHANGETYPE_NONE;
    1415                 ldif.msg = msg;
    1416                 ldif_string = ldb_ldif_write_string(ldb, NULL, &ldif);
    1417                 ldb_debug(ldb, LDB_DEBUG_ERROR,
    1418                           "ERROR: dn %s not found in %s", dn,
    1419                           ldif_string);
    1420                 talloc_free(ldif_string);
    1421                 /* it ain't there. hmmm */
    1422                 talloc_free(dn_key);
    1423                 return LDB_SUCCESS;
    1424         }
    1425 
    1426         if (j != msg->elements[i].num_values - 1) {
    1427                 memmove(&msg->elements[i].values[j],
    1428                         &msg->elements[i].values[j+1],
    1429                         (msg->elements[i].num_values-(j+1)) *
    1430                         sizeof(msg->elements[i].values[0]));
    1431         }
    1432         msg->elements[i].num_values--;
    1433 
    1434         if (msg->elements[i].num_values == 0) {
    1435                 ret = ltdb_delete_noindex(module, dn_key);
    1436         } else {
    1437                 ret = ltdb_store_idxptr(module, msg, TDB_REPLACE);
    1438         }
    1439 
    1440         talloc_free(dn_key);
    1441 
    1442         return ret;
    1443 }
    1444 
    1445 /*
    1446   delete the index entries for a record
    1447   return -1 on failure
    1448 */
    1449 int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg)
    1450 {
    1451         void *data = ldb_module_get_private(module);
    1452         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    1453         int ret;
    1454         const char *dn;
    1455         unsigned int i, j;
    1456 
    1457         /* find the list of indexed fields */
    1458         if (ltdb->cache->indexlist->num_elements == 0) {
    1459                 /* no indexed fields */
    1460                 return LDB_SUCCESS;
    1461         }
    1462 
    1463         if (ldb_dn_is_special(msg->dn)) {
    1464                 return LDB_SUCCESS;
    1465         }
    1466 
    1467         dn = ldb_dn_get_linearized(msg->dn);
    1468         if (dn == NULL) {
    1469                 return LDB_ERR_OPERATIONS_ERROR;
    1470         }
    1471 
    1472         for (i = 0; i < msg->num_elements; i++) {
    1473                 ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name,
    1474                                        NULL, LTDB_IDXATTR);
    1475                 if (ret == -1) {
    1476                         continue;
    1477                 }
    1478                 for (j = 0; j < msg->elements[i].num_values; j++) {
    1479                         ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
    1480                         if (ret != LDB_SUCCESS) {
    1481                                 return ret;
    1482                         }
    1483                 }
    1484         }
    1485 
    1486         return LDB_SUCCESS;
    1487 }
    1488 
    1489 /*
    1490   handle special index for one level searches
    1491 */
    1492 int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add)
    1493 {
    1494         void *data = ldb_module_get_private(module);
    1495         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
     1198
     1199/*
     1200  insert a one level index for a message
     1201*/
     1202static int ltdb_index_onelevel(struct ldb_module *module, const struct ldb_message *msg, int add)
     1203{
     1204        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
    14961205        struct ldb_message_element el;
    14971206        struct ldb_val val;
     
    15001209        int ret;
    15011210
    1502         if (ldb_dn_is_special(msg->dn)) {
    1503                 return LDB_SUCCESS;
    1504         }
    1505 
    15061211        /* We index for ONE Level only if requested */
    1507         ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
    1508         if (ret != 0) {
     1212        if (!ltdb->cache->one_level_indexes) {
    15091213                return LDB_SUCCESS;
    15101214        }
     
    15351239                ret = ltdb_index_add1(module, dn, &el, 0);
    15361240        } else { /* delete */
    1537                 ret = ltdb_index_del_value(module, dn, &el, 0);
     1241                ret = ltdb_index_del_value(module, msg->dn, &el, 0);
    15381242        }
    15391243
     
    15431247}
    15441248
     1249/*
     1250  add the index entries for a new element in a record
     1251  The caller guarantees that these element values are not yet indexed
     1252*/
     1253int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
     1254                           struct ldb_message_element *el)
     1255{
     1256        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     1257        if (ldb_dn_is_special(dn)) {
     1258                return LDB_SUCCESS;
     1259        }
     1260        if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
     1261                return LDB_SUCCESS;
     1262        }
     1263        return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el);
     1264}
     1265
     1266/*
     1267  add the index entries for a new record
     1268*/
     1269int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg)
     1270{
     1271        const char *dn;
     1272        int ret;
     1273
     1274        if (ldb_dn_is_special(msg->dn)) {
     1275                return LDB_SUCCESS;
     1276        }
     1277
     1278        dn = ldb_dn_get_linearized(msg->dn);
     1279        if (dn == NULL) {
     1280                return LDB_ERR_OPERATIONS_ERROR;
     1281        }
     1282
     1283        ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements);
     1284        if (ret != LDB_SUCCESS) {
     1285                return ret;
     1286        }
     1287
     1288        return ltdb_index_onelevel(module, msg, 1);
     1289}
     1290
     1291
     1292/*
     1293  delete an index entry for one message element
     1294*/
     1295int ltdb_index_del_value(struct ldb_module *module, struct ldb_dn *dn,
     1296                         struct ldb_message_element *el, unsigned int v_idx)
     1297{
     1298        struct ldb_context *ldb;
     1299        struct ldb_dn *dn_key;
     1300        const char *dn_str;
     1301        int ret, i;
     1302        unsigned int j;
     1303        struct dn_list *list;
     1304
     1305        ldb = ldb_module_get_ctx(module);
     1306
     1307        dn_str = ldb_dn_get_linearized(dn);
     1308        if (dn_str == NULL) {
     1309                return LDB_ERR_OPERATIONS_ERROR;
     1310        }
     1311
     1312        if (dn_str[0] == '@') {
     1313                return LDB_SUCCESS;
     1314        }
     1315
     1316        dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
     1317        if (!dn_key) {
     1318                return LDB_ERR_OPERATIONS_ERROR;
     1319        }
     1320
     1321        list = talloc_zero(dn_key, struct dn_list);
     1322        if (list == NULL) {
     1323                talloc_free(dn_key);
     1324                return LDB_ERR_OPERATIONS_ERROR;
     1325        }
     1326
     1327        ret = ltdb_dn_list_load(module, dn_key, list);
     1328        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     1329                /* it wasn't indexed. Did we have an earlier error? If we did then
     1330                   its gone now */
     1331                talloc_free(dn_key);
     1332                return LDB_SUCCESS;
     1333        }
     1334
     1335        if (ret != LDB_SUCCESS) {
     1336                talloc_free(dn_key);
     1337                return ret;
     1338        }
     1339
     1340        i = ltdb_dn_list_find_str(list, dn_str);
     1341        if (i == -1) {
     1342                /* nothing to delete */
     1343                talloc_free(dn_key);
     1344                return LDB_SUCCESS;             
     1345        }
     1346
     1347        j = (unsigned int) i;
     1348        if (j != list->count - 1) {
     1349                memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1)));
     1350        }
     1351        list->count--;
     1352        list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
     1353
     1354        ret = ltdb_dn_list_store(module, dn_key, list);
     1355
     1356        talloc_free(dn_key);
     1357
     1358        return ret;
     1359}
     1360
     1361/*
     1362  delete the index entries for a element
     1363  return -1 on failure
     1364*/
     1365int ltdb_index_del_element(struct ldb_module *module, struct ldb_dn *dn,
     1366                           struct ldb_message_element *el)
     1367{
     1368        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     1369        const char *dn_str;
     1370        int ret;
     1371        unsigned int i;
     1372
     1373        if (!ltdb->cache->attribute_indexes) {
     1374                /* no indexed fields */
     1375                return LDB_SUCCESS;
     1376        }
     1377
     1378        dn_str = ldb_dn_get_linearized(dn);
     1379        if (dn_str == NULL) {
     1380                return LDB_ERR_OPERATIONS_ERROR;
     1381        }
     1382
     1383        if (dn_str[0] == '@') {
     1384                return LDB_SUCCESS;
     1385        }
     1386
     1387        if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
     1388                return LDB_SUCCESS;
     1389        }
     1390        for (i = 0; i < el->num_values; i++) {
     1391                ret = ltdb_index_del_value(module, dn, el, i);
     1392                if (ret != LDB_SUCCESS) {
     1393                        return ret;
     1394                }
     1395        }
     1396
     1397        return LDB_SUCCESS;
     1398}
     1399
     1400/*
     1401  delete the index entries for a record
     1402  return -1 on failure
     1403*/
     1404int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg)
     1405{
     1406        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     1407        int ret;
     1408        unsigned int i;
     1409
     1410        if (ldb_dn_is_special(msg->dn)) {
     1411                return LDB_SUCCESS;
     1412        }
     1413
     1414        ret = ltdb_index_onelevel(module, msg, 0);
     1415        if (ret != LDB_SUCCESS) {
     1416                return ret;
     1417        }
     1418
     1419        if (!ltdb->cache->attribute_indexes) {
     1420                /* no indexed fields */
     1421                return LDB_SUCCESS;
     1422        }
     1423
     1424        for (i = 0; i < msg->num_elements; i++) {
     1425                ret = ltdb_index_del_element(module, msg->dn, &msg->elements[i]);
     1426                if (ret != LDB_SUCCESS) {
     1427                        return ret;
     1428                }
     1429        }
     1430
     1431        return LDB_SUCCESS;
     1432}
     1433
    15451434
    15461435/*
     
    15491438static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
    15501439{
    1551         const char *dn = "DN=" LTDB_INDEX ":";
    1552         if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) {
    1553                 return tdb_delete(tdb, key);
    1554         }
     1440        struct ldb_module *module = state;
     1441        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     1442        const char *dnstr = "DN=" LTDB_INDEX ":";
     1443        struct dn_list list;
     1444        struct ldb_dn *dn;
     1445        struct ldb_val v;
     1446        int ret;
     1447
     1448        if (strncmp((char *)key.dptr, dnstr, strlen(dnstr)) != 0) {
     1449                return 0;
     1450        }
     1451        /* we need to put a empty list in the internal tdb for this
     1452         * index entry */
     1453        list.dn = NULL;
     1454        list.count = 0;
     1455
     1456        /* the offset of 3 is to remove the DN= prefix. */
     1457        v.data = key.dptr + 3;
     1458        v.length = strnlen((char *)key.dptr, key.dsize) - 3;
     1459
     1460        dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v);
     1461        ret = ltdb_dn_list_store(module, dn, &list);
     1462        if (ret != LDB_SUCCESS) {
     1463                ldb_asprintf_errstring(ldb_module_get_ctx(module),
     1464                                       "Unable to store null index for %s\n",
     1465                                                ldb_dn_get_linearized(dn));
     1466                talloc_free(dn);
     1467                return -1;
     1468        }
     1469        talloc_free(dn);
    15551470        return 0;
    15561471}
    15571472
     1473struct ltdb_reindex_context {
     1474        struct ldb_module *module;
     1475        int error;
     1476};
     1477
    15581478/*
    15591479  traversal function that adds @INDEX records during a re index
     
    15621482{
    15631483        struct ldb_context *ldb;
    1564         struct ldb_module *module = (struct ldb_module *)state;
     1484        struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
     1485        struct ldb_module *module = ctx->module;
    15651486        struct ldb_message *msg;
    15661487        const char *dn = NULL;
     
    15751496        }
    15761497
    1577         msg = talloc(module, struct ldb_message);
     1498        msg = ldb_msg_new(module);
    15781499        if (msg == NULL) {
    15791500                return -1;
     
    15831504        if (ret != 0) {
    15841505                ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
    1585                           ldb_dn_get_linearized(msg->dn));
     1506                                                ldb_dn_get_linearized(msg->dn));
    15861507                talloc_free(msg);
    15871508                return -1;
     
    15941515                /* probably a corrupt record ... darn */
    15951516                ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
    1596                                                         ldb_dn_get_linearized(msg->dn));
     1517                                                ldb_dn_get_linearized(msg->dn));
    15971518                talloc_free(msg);
    15981519                return 0;
     
    16101531        }
    16111532
    1612         ret = ltdb_index_one(module, msg, 1);
    1613         if (ret == LDB_SUCCESS) {
    1614                 ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
    1615         } else {
     1533        ret = ltdb_index_onelevel(module, msg, 1);
     1534        if (ret != LDB_SUCCESS) {
    16161535                ldb_debug(ldb, LDB_DEBUG_ERROR,
    1617                         "Adding special ONE LEVEL index failed (%s)!",
    1618                         ldb_dn_get_linearized(msg->dn));
     1536                          "Adding special ONE LEVEL index failed (%s)!",
     1537                                                ldb_dn_get_linearized(msg->dn));
     1538                talloc_free(msg);
     1539                return -1;
     1540        }
     1541
     1542        ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements);
     1543
     1544        if (ret != LDB_SUCCESS) {
     1545                ctx->error = ret;
     1546                talloc_free(msg);
     1547                return -1;
    16191548        }
    16201549
    16211550        talloc_free(msg);
    16221551
    1623         if (ret != LDB_SUCCESS) return -1;
    1624 
    16251552        return 0;
    16261553}
     
    16311558int ltdb_reindex(struct ldb_module *module)
    16321559{
    1633         void *data = ldb_module_get_private(module);
    1634         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
     1560        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
    16351561        int ret;
     1562        struct ltdb_reindex_context ctx;
    16361563
    16371564        if (ltdb_cache_reload(module) != 0) {
     
    16391566        }
    16401567
    1641         /* first traverse the database deleting any @INDEX records */
    1642         ret = tdb_traverse(ltdb->tdb, delete_index, NULL);
     1568        /* first traverse the database deleting any @INDEX records by
     1569         * putting NULL entries in the in-memory tdb
     1570         */
     1571        ret = tdb_traverse(ltdb->tdb, delete_index, module);
    16431572        if (ret == -1) {
    16441573                return LDB_ERR_OPERATIONS_ERROR;
     
    16501579        }
    16511580
     1581        ctx.module = module;
     1582        ctx.error = 0;
     1583
    16521584        /* now traverse adding any indexes for normal LDB records */
    1653         ret = tdb_traverse(ltdb->tdb, re_index, module);
     1585        ret = tdb_traverse(ltdb->tdb, re_index, &ctx);
    16541586        if (ret == -1) {
    1655                 return LDB_ERR_OPERATIONS_ERROR;
    1656         }
    1657 
    1658         if (ltdb->idxptr) {
    1659                 ltdb->idxptr->repack = true;
     1587                struct ldb_context *ldb = ldb_module_get_ctx(module);
     1588                ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s", ldb_errstring(ldb));
     1589                return LDB_ERR_OPERATIONS_ERROR;
     1590        }
     1591
     1592        if (ctx.error != LDB_SUCCESS) {
     1593                struct ldb_context *ldb = ldb_module_get_ctx(module);
     1594                ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));
     1595                return ctx.error;
    16601596        }
    16611597
  • trunk/server/source4/lib/ldb/ldb_tdb/ldb_pack.c

    r414 r745  
    5959{
    6060        if (el->num_values == 0) return 0;
    61 
    62         if (ldb_attr_cmp(el->name, "dn") == 0) return 0;
    6361
    6462        if (ldb_attr_cmp(el->name, "distinguishedName") == 0) return 0;
     
    209207
    210208        if (message->num_elements == 0) {
    211                 message->elements = NULL;
    212209                return 0;
    213210        }
  • trunk/server/source4/lib/ldb/ldb_tdb/ldb_search.c

    r414 r745  
    7979
    8080        elnew->num_values = el->num_values;
     81        elnew->flags = el->flags;
    8182
    8283        ret->num_elements++;
     
    9899        el.num_values = 1;
    99100        el.values = &val;
     101        el.flags = 0;
    100102        val.data = (uint8_t *)ldb_dn_alloc_linearized(msg, msg->dn);
    101103        val.length = strlen((char *)val.data);
     
    146148{
    147149        struct ldb_message *ret;
    148         int i;
     150        unsigned int i;
    149151
    150152        ret = talloc(mem_ctx, struct ldb_message);
     
    326328int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs)
    327329{
    328         int i, keep_all = 0;
     330        unsigned int i;
     331        int keep_all = 0;
     332        struct ldb_message_element *el2;
     333        uint32_t num_elements;
    329334
    330335        if (attrs) {
     
    353358        }
    354359
     360        el2 = talloc_array(msg, struct ldb_message_element, msg->num_elements);
     361        if (el2 == NULL) {
     362                return -1;
     363        }
     364        num_elements = 0;
     365
    355366        for (i = 0; i < msg->num_elements; i++) {
    356                 int j, found;
     367                unsigned int j;
     368                int found = 0;
    357369               
    358                 for (j = 0, found = 0; attrs[j]; j++) {
     370                for (j = 0; attrs[j]; j++) {
    359371                        if (ldb_attr_cmp(msg->elements[i].name, attrs[j]) == 0) {
    360372                                found = 1;
     
    363375                }
    364376
    365                 if (!found) {
    366                         ldb_msg_remove_attr(msg, msg->elements[i].name);
    367                         i--;
    368                 }
    369         }
     377                if (found) {
     378                        el2[num_elements] = msg->elements[i];
     379                        talloc_steal(el2, el2[num_elements].name);
     380                        talloc_steal(el2, el2[num_elements].values);
     381                        num_elements++;
     382                }
     383        }
     384
     385        talloc_free(msg->elements);
     386        msg->elements = talloc_realloc(msg, el2, struct ldb_message_element, msg->num_elements);
     387        if (msg->elements == NULL) {
     388                return -1;
     389        }
     390        msg->num_elements = num_elements;
    370391
    371392        return 0;
     
    381402        struct ldb_message *msg;
    382403        int ret;
     404        bool matched;
    383405
    384406        ac = talloc_get_type(state, struct ltdb_context);
     
    412434
    413435        /* see if it matches the given expression */
    414         if (!ldb_match_msg(ldb, msg,
    415                            ac->tree, ac->base, ac->scope)) {
     436        ret = ldb_match_msg_error(ldb, msg,
     437                                  ac->tree, ac->base, ac->scope, &matched);
     438        if (ret != LDB_SUCCESS) {
     439                talloc_free(msg);
     440                return -1;
     441        }
     442        if (!matched) {
    416443                talloc_free(msg);
    417444                return 0;
     
    552579                if ( ! ctx->request_terminated && ret != LDB_SUCCESS) {
    553580                        /* Not indexed, so we need to do a full scan */
    554 #if 0
    555                         /* useful for debugging when slow performance
    556                          * is caused by unindexed searches */
    557                         char *expression = ldb_filter_from_tree(ctx, ctx->tree);
    558                         printf("FULL SEARCH: %s\n", expression);
    559                         talloc_free(expression);
    560 #endif
     581                        if (ltdb->warn_unindexed) {
     582                                /* useful for debugging when slow performance
     583                                 * is caused by unindexed searches */
     584                                char *expression = ldb_filter_from_tree(ctx, ctx->tree);
     585                                ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb FULL SEARCH: %s SCOPE: %s DN: %s\n",
     586                                                        expression,
     587                                                        req->op.search.scope==LDB_SCOPE_BASE?"base":
     588                                                        req->op.search.scope==LDB_SCOPE_ONELEVEL?"one":
     589                                                        req->op.search.scope==LDB_SCOPE_SUBTREE?"sub":"UNKNOWN",
     590                                                        ldb_dn_get_linearized(req->op.search.base));
     591
     592                                talloc_free(expression);
     593                        }
    561594                        if (match_count != 0) {
    562595                                /* the indexing code gave an error
     
    568601                                 * duplicate entries
    569602                                 */
     603                                ltdb_unlock_read(module);
    570604                                return LDB_ERR_OPERATIONS_ERROR;
    571605                        }
  • trunk/server/source4/lib/ldb/ldb_tdb/ldb_tdb.c

    r414 r745  
    22   ldb database library
    33
    4    Copyright (C) Andrew Tridgell  2004
    5    Copyright (C) Stefan Metzmacher  2004
    6    Copyright (C) Simo Sorce       2006-2008
    7 
     4   Copyright (C) Andrew Tridgell 2004
     5   Copyright (C) Stefan Metzmacher 2004
     6   Copyright (C) Simo Sorce 2006-2008
     7   Copyright (C) Matthias Dieter Wallnöfer 2009-2010
    88
    99     ** NOTE! The following LGPL license applies to the ldb
     
    3737 *  Modifications:
    3838 *
    39  *  - description: make the module use asyncronous calls
     39 *  - description: make the module use asynchronous calls
    4040 *    date: Feb 2006
    4141 *    Author: Simo Sorce
     
    4444 *    date: Jan 2008
    4545 *    Author: Simo Sorce
     46 *
     47 *  - description: fix up memory leaks and small bugs
     48 *    date: Oct 2009
     49 *    Author: Matthias Dieter Wallnöfer
    4650 */
    4751
     
    5256  map a tdb error code to a ldb error code
    5357*/
    54 static int ltdb_err_map(enum TDB_ERROR tdb_code)
     58int ltdb_err_map(enum TDB_ERROR tdb_code)
    5559{
    5660        switch (tdb_code) {
     
    7478        case TDB_ERR_RDONLY:
    7579                return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
     80        default:
     81                break;
    7682        }
    7783        return LDB_ERR_OTHER;
     
    8591        void *data = ldb_module_get_private(module);
    8692        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    87         if (ltdb->in_transaction == 0) {
    88                 return tdb_lockall_read(ltdb->tdb);
    89         }
    90         return 0;
     93        int ret = 0;
     94
     95        if (ltdb->in_transaction == 0 &&
     96            ltdb->read_lock_count == 0) {
     97                ret = tdb_lockall_read(ltdb->tdb);
     98        }
     99        if (ret == 0) {
     100                ltdb->read_lock_count++;
     101        }
     102        return ret;
    91103}
    92104
     
    98110        void *data = ldb_module_get_private(module);
    99111        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    100         if (ltdb->in_transaction == 0) {
     112        if (ltdb->in_transaction == 0 && ltdb->read_lock_count == 1) {
    101113                return tdb_unlockall_read(ltdb->tdb);
    102114        }
     115        ltdb->read_lock_count--;
    103116        return 0;
    104117}
     
    163176*/
    164177static int ltdb_check_special_dn(struct ldb_module *module,
    165                           const struct ldb_message *msg)
     178                                const struct ldb_message *msg)
    166179{
    167180        struct ldb_context *ldb = ldb_module_get_ctx(module);
    168         int i, j;
     181        unsigned int i, j;
    169182
    170183        if (! ldb_dn_is_special(msg->dn) ||
    171184            ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
    172                 return 0;
     185                return LDB_SUCCESS;
    173186        }
    174187
     
    176189        /* should we check that we deny multivalued attributes ? */
    177190        for (i = 0; i < msg->num_elements; i++) {
     191                if (ldb_attr_cmp(msg->elements[i].name, "distinguishedName") == 0) continue;
     192
    178193                for (j = 0; j < msg->elements[i].num_values; j++) {
    179194                        if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
     
    184199        }
    185200
    186         return 0;
     201        return LDB_SUCCESS;
    187202}
    188203
     
    195210{
    196211        int ret = LDB_SUCCESS;
     212        struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
     213
     214        /* only allow modifies inside a transaction, otherwise the
     215         * ldb is unsafe */
     216        if (ltdb->in_transaction == 0) {
     217                ldb_set_errstring(ldb_module_get_ctx(module), "ltdb modify without transaction");
     218                return LDB_ERR_OPERATIONS_ERROR;
     219        }
    197220
    198221        if (ldb_dn_is_special(dn) &&
     
    202225        }
    203226
     227        /* If the modify was to a normal record, or any special except @BASEINFO, update the seq number */
    204228        if (ret == LDB_SUCCESS &&
    205229            !(ldb_dn_is_special(dn) &&
     
    208232        }
    209233
     234        /* If the modify was to @OPTIONS, reload the cache */
     235        if (ret == LDB_SUCCESS &&
     236            ldb_dn_is_special(dn) &&
     237            (ldb_dn_check_special(dn, LTDB_OPTIONS)) ) {
     238                ret = ltdb_cache_reload(module);
     239        }
     240
    210241        return ret;
    211242}
     
    219250        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
    220251        TDB_DATA tdb_key, tdb_data;
    221         int ret;
     252        int ret = LDB_SUCCESS;
    222253
    223254        tdb_key = ltdb_key(module, msg->dn);
    224         if (!tdb_key.dptr) {
     255        if (tdb_key.dptr == NULL) {
    225256                return LDB_ERR_OTHER;
    226257        }
     
    238269        }
    239270
    240         ret = ltdb_index_add(module, msg);
    241         if (ret != LDB_SUCCESS) {
    242                 tdb_delete(ltdb->tdb, tdb_key);
    243         }
    244 
    245271done:
    246272        talloc_free(tdb_key.dptr);
     
    251277
    252278
     279/*
     280  check if a attribute is a single valued, for a given element
     281 */
     282static bool ldb_tdb_single_valued(const struct ldb_schema_attribute *a,
     283                                  struct ldb_message_element *el)
     284{
     285        if (!a) return false;
     286        if (el != NULL) {
     287                if (el->flags & LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK) {
     288                        /* override from a ldb module, for example
     289                           used for the description field, which is
     290                           marked multi-valued in the schema but which
     291                           should not actually accept multiple
     292                           values */
     293                        return true;
     294                }
     295                if (el->flags & LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK) {
     296                        /* override from a ldb module, for example used for
     297                           deleted linked attribute entries */
     298                        return false;
     299                }
     300        }
     301        if (a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
     302                return true;
     303        }
     304        return false;
     305}
     306
    253307static int ltdb_add_internal(struct ldb_module *module,
    254308                             const struct ldb_message *msg)
    255309{
    256310        struct ldb_context *ldb = ldb_module_get_ctx(module);
    257         int ret, i;
    258 
    259         ret = ltdb_check_special_dn(module, msg);
    260         if (ret != LDB_SUCCESS) {
    261                 return ret;
    262         }
    263 
    264         if (ltdb_cache_load(module) != 0) {
    265                 return LDB_ERR_OPERATIONS_ERROR;
    266         }
     311        int ret = LDB_SUCCESS;
     312        unsigned int i;
    267313
    268314        for (i=0;i<msg->num_elements;i++) {
     
    271317
    272318                if (el->num_values == 0) {
    273                         ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illegal)",
     319                        ldb_asprintf_errstring(ldb, "attribute '%s' on '%s' specified, but with 0 values (illegal)",
    274320                                               el->name, ldb_dn_get_linearized(msg->dn));
    275321                        return LDB_ERR_CONSTRAINT_VIOLATION;
    276322                }
    277                 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
    278                         if (el->num_values > 1) {
    279                                 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
    280                                                        el->name, ldb_dn_get_linearized(msg->dn));
    281                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    282                         }
     323                if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) {
     324                        ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
     325                                               el->name, ldb_dn_get_linearized(msg->dn));
     326                        return LDB_ERR_CONSTRAINT_VIOLATION;
    283327                }
    284328        }
    285329
    286330        ret = ltdb_store(module, msg, TDB_INSERT);
    287 
    288         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
    289                 ldb_asprintf_errstring(ldb,
    290                                         "Entry %s already exists",
    291                                         ldb_dn_get_linearized(msg->dn));
     331        if (ret != LDB_SUCCESS) {
     332                if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
     333                        ldb_asprintf_errstring(ldb,
     334                                               "Entry %s already exists",
     335                                               ldb_dn_get_linearized(msg->dn));
     336                }
    292337                return ret;
    293338        }
    294339
    295         if (ret == LDB_SUCCESS) {
    296                 ret = ltdb_index_one(module, msg, 1);
    297                 if (ret != LDB_SUCCESS) {
    298                         return ret;
    299                 }
    300 
    301                 ret = ltdb_modified(module, msg->dn);
    302                 if (ret != LDB_SUCCESS) {
    303                         return ret;
    304                 }
    305         }
     340        ret = ltdb_index_add_new(module, msg);
     341        if (ret != LDB_SUCCESS) {
     342                return ret;
     343        }
     344
     345        ret = ltdb_modified(module, msg->dn);
    306346
    307347        return ret;
     
    315355        struct ldb_module *module = ctx->module;
    316356        struct ldb_request *req = ctx->req;
    317         int tret;
     357        int ret = LDB_SUCCESS;
     358
     359        ret = ltdb_check_special_dn(module, req->op.add.message);
     360        if (ret != LDB_SUCCESS) {
     361                return ret;
     362        }
    318363
    319364        ldb_request_set_state(req, LDB_ASYNC_PENDING);
    320365
    321         tret = ltdb_add_internal(module, req->op.add.message);
    322         if (tret != LDB_SUCCESS) {
    323                 return tret;
    324         }
    325 
    326         return LDB_SUCCESS;
     366        if (ltdb_cache_load(module) != 0) {
     367                return LDB_ERR_OPERATIONS_ERROR;
     368        }
     369
     370        ret = ltdb_add_internal(module, req->op.add.message);
     371
     372        return ret;
    327373}
    328374
     
    356402{
    357403        struct ldb_message *msg;
    358         int ret;
    359 
    360         msg = talloc(module, struct ldb_message);
     404        int ret = LDB_SUCCESS;
     405
     406        msg = ldb_msg_new(module);
    361407        if (msg == NULL) {
    362408                return LDB_ERR_OPERATIONS_ERROR;
     
    376422        }
    377423
    378         /* remove one level attribute */
    379         ret = ltdb_index_one(module, msg, 0);
    380         if (ret != LDB_SUCCESS) {
    381                 goto done;
    382         }
    383 
    384424        /* remove any indexed attributes */
    385         ret = ltdb_index_del(module, msg);
     425        ret = ltdb_index_delete(module, msg);
    386426        if (ret != LDB_SUCCESS) {
    387427                goto done;
     
    405445        struct ldb_module *module = ctx->module;
    406446        struct ldb_request *req = ctx->req;
    407         int tret;
     447        int ret = LDB_SUCCESS;
    408448
    409449        ldb_request_set_state(req, LDB_ASYNC_PENDING);
     
    413453        }
    414454
    415         tret = ltdb_delete_internal(module, req->op.del.dn);
    416         if (tret != LDB_SUCCESS) {
    417                 return tret;
    418         }
    419 
    420         return LDB_SUCCESS;
     455        ret = ltdb_delete_internal(module, req->op.del.dn);
     456
     457        return ret;
    421458}
    422459
     
    447484  returns 0 on success, -1 on failure (and sets errno)
    448485*/
    449 static int msg_add_element(struct ldb_context *ldb,
    450                            struct ldb_message *msg,
    451                            struct ldb_message_element *el)
     486static int ltdb_msg_add_element(struct ldb_context *ldb,
     487                                struct ldb_message *msg,
     488                                struct ldb_message_element *el)
    452489{
    453490        struct ldb_message_element *e2;
    454491        unsigned int i;
     492
     493        if (el->num_values == 0) {
     494                /* nothing to do here - we don't add empty elements */
     495                return 0;
     496        }
    455497
    456498        e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
     
    467509        e2->name = el->name;
    468510        e2->flags = el->flags;
    469         e2->values = NULL;
    470         if (el->num_values != 0) {
    471                 e2->values = talloc_array(msg->elements,
    472                                           struct ldb_val, el->num_values);
    473                 if (!e2->values) {
    474                         errno = ENOMEM;
    475                         return -1;
    476                 }
     511        e2->values = talloc_array(msg->elements,
     512                                  struct ldb_val, el->num_values);
     513        if (!e2->values) {
     514                errno = ENOMEM;
     515                return -1;
    477516        }
    478517        for (i=0;i<el->num_values;i++) {
     
    481520        e2->num_values = el->num_values;
    482521
    483         msg->num_elements++;
     522        ++msg->num_elements;
    484523
    485524        return 0;
     
    493532                                struct ldb_message *msg, const char *name)
    494533{
    495         const char *dn;
    496         unsigned int i, j;
    497 
    498         dn = ldb_dn_get_linearized(msg->dn);
    499         if (dn == NULL) {
    500                 return -1;
    501         }
    502 
    503         for (i=0;i<msg->num_elements;i++) {
    504                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
    505                         for (j=0;j<msg->elements[i].num_values;j++) {
    506                                 ltdb_index_del_value(module, dn,
    507                                                      &msg->elements[i], j);
    508                         }
    509                         talloc_free(msg->elements[i].values);
    510                         if (msg->num_elements > (i+1)) {
    511                                 memmove(&msg->elements[i],
    512                                         &msg->elements[i+1],
    513                                         sizeof(struct ldb_message_element)*
    514                                         (msg->num_elements - (i+1)));
    515                         }
    516                         msg->num_elements--;
    517                         i--;
    518                         msg->elements = talloc_realloc(msg, msg->elements,
    519                                                         struct ldb_message_element,
    520                                                         msg->num_elements);
    521                 }
    522         }
    523 
    524         return 0;
     534        unsigned int i;
     535        int ret;
     536        struct ldb_message_element *el;
     537
     538        el = ldb_msg_find_element(msg, name);
     539        if (el == NULL) {
     540                return LDB_ERR_NO_SUCH_ATTRIBUTE;
     541        }
     542        i = el - msg->elements;
     543
     544        ret = ltdb_index_del_element(module, msg->dn, el);
     545        if (ret != LDB_SUCCESS) {
     546                return ret;
     547        }
     548
     549        talloc_free(el->values);
     550        if (msg->num_elements > (i+1)) {
     551                memmove(el, el+1, sizeof(*el) * (msg->num_elements - (i+1)));
     552        }
     553        msg->num_elements--;
     554        msg->elements = talloc_realloc(msg, msg->elements,
     555                                       struct ldb_message_element,
     556                                       msg->num_elements);
     557        return LDB_SUCCESS;
    525558}
    526559
     
    528561  delete all elements matching an attribute name/value
    529562
    530   return 0 on success, -1 on failure
     563  return LDB Error on failure
    531564*/
    532565static int msg_delete_element(struct ldb_module *module,
     
    537570        struct ldb_context *ldb = ldb_module_get_ctx(module);
    538571        unsigned int i;
    539         int found;
     572        int found, ret;
    540573        struct ldb_message_element *el;
    541574        const struct ldb_schema_attribute *a;
     
    543576        found = find_element(msg, name);
    544577        if (found == -1) {
    545                 return -1;
    546         }
    547 
    548         el = &msg->elements[found];
     578                return LDB_ERR_NO_SUCH_ATTRIBUTE;
     579        }
     580
     581        i = (unsigned int) found;
     582        el = &(msg->elements[i]);
    549583
    550584        a = ldb_schema_attribute_by_name(ldb, el->name);
    551585
    552586        for (i=0;i<el->num_values;i++) {
    553                 if (a->syntax->comparison_fn(ldb, ldb,
    554                                                 &el->values[i], val) == 0) {
     587                bool matched;
     588                if (a->syntax->operator_fn) {
     589                        ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
     590                                                     &el->values[i], val, &matched);
     591                        if (ret != LDB_SUCCESS) return ret;
     592                } else {
     593                        matched = (a->syntax->comparison_fn(ldb, ldb,
     594                                                            &el->values[i], val) == 0);
     595                }
     596                if (matched) {
     597                        if (el->num_values == 1) {
     598                                return msg_delete_attribute(module, ldb, msg, name);
     599                        }
     600
     601                        ret = ltdb_index_del_value(module, msg->dn, el, i);
     602                        if (ret != LDB_SUCCESS) {
     603                                return ret;
     604                        }
     605
    555606                        if (i<el->num_values-1) {
    556607                                memmove(&el->values[i], &el->values[i+1],
     
    559610                        }
    560611                        el->num_values--;
    561                         if (el->num_values == 0) {
    562                                 return msg_delete_attribute(module, ldb,
    563                                                             msg, name);
    564                         }
    565                         return 0;
     612
     613                        /* per definition we find in a canonicalised message an
     614                           attribute value only once. So we are finished here */
     615                        return LDB_SUCCESS;
    566616                }
    567617        }
    568618
    569         return -1;
     619        /* Not found */
     620        return LDB_ERR_NO_SUCH_ATTRIBUTE;
    570621}
    571622
     
    577628  get away with it, but if we ever have really large attribute lists
    578629  then we'll need to look at this again
     630
     631  'req' is optional, and is used to specify controls if supplied
    579632*/
    580633int ltdb_modify_internal(struct ldb_module *module,
    581                          const struct ldb_message *msg)
     634                         const struct ldb_message *msg,
     635                         struct ldb_request *req)
    582636{
    583637        struct ldb_context *ldb = ldb_module_get_ctx(module);
     
    586640        TDB_DATA tdb_key, tdb_data;
    587641        struct ldb_message *msg2;
    588         unsigned i, j;
    589         int ret, idx;
     642        unsigned int i, j, k;
     643        int ret = LDB_SUCCESS, idx;
     644        struct ldb_control *control_permissive = NULL;
     645
     646        if (req) {
     647                control_permissive = ldb_request_get_control(req,
     648                                        LDB_CONTROL_PERMISSIVE_MODIFY_OID);
     649        }
    590650
    591651        tdb_key = ltdb_key(module, msg->dn);
     
    600660        }
    601661
    602         msg2 = talloc(tdb_key.dptr, struct ldb_message);
     662        msg2 = ldb_msg_new(tdb_key.dptr);
    603663        if (msg2 == NULL) {
    604                 talloc_free(tdb_key.dptr);
    605                 return LDB_ERR_OTHER;
     664                free(tdb_data.dptr);
     665                ret = LDB_ERR_OTHER;
     666                goto done;
    606667        }
    607668
    608669        ret = ltdb_unpack_data(module, &tdb_data, msg2);
     670        free(tdb_data.dptr);
    609671        if (ret == -1) {
    610672                ret = LDB_ERR_OTHER;
    611                 goto failed;
     673                goto done;
    612674        }
    613675
     
    616678        }
    617679
    618         for (i=0;i<msg->num_elements;i++) {
    619                 struct ldb_message_element *el = &msg->elements[i];
    620                 struct ldb_message_element *el2;
     680        for (i=0; i<msg->num_elements; i++) {
     681                struct ldb_message_element *el = &msg->elements[i], *el2;
    621682                struct ldb_val *vals;
     683                const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
    622684                const char *dn;
    623                 const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
     685
    624686                switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
    625 
    626687                case LDB_FLAG_MOD_ADD:
    627                        
    628                         /* add this element to the message. fail if it
    629                            already exists */
     688
     689                        if (el->num_values == 0) {
     690                                ldb_asprintf_errstring(ldb,
     691                                                       "attribute '%s': attribute on '%s' specified, but with 0 values (illegal)",
     692                                                       el->name, ldb_dn_get_linearized(msg2->dn));
     693                                ret = LDB_ERR_CONSTRAINT_VIOLATION;
     694                                goto done;
     695                        }
     696
     697                        /* make a copy of the array so that a permissive
     698                         * control can remove duplicates without changing the
     699                         * original values, but do not copy data as we do not
     700                         * need to keep it around once the operation is
     701                         * finished */
     702                        if (control_permissive) {
     703                                el = talloc(msg2, struct ldb_message_element);
     704                                if (!el) {
     705                                        ret = LDB_ERR_OTHER;
     706                                        goto done;
     707                                }
     708                                *el = msg->elements[i];
     709                                el->values = talloc_array(el, struct ldb_val, el->num_values);
     710                                if (el->values == NULL) {
     711                                        ret = LDB_ERR_OTHER;
     712                                        goto done;
     713                                }
     714                                for (j = 0; j < el->num_values; j++) {
     715                                        el->values[j] = msg->elements[i].values[j];
     716                                }
     717                        }
     718
     719                        if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) {
     720                                ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
     721                                                       el->name, ldb_dn_get_linearized(msg2->dn));
     722                                ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     723                                goto done;
     724                        }
     725
     726                        /* Checks if element already exists */
    630727                        idx = find_element(msg2, el->name);
    631 
    632                         if (el->num_values == 0) {
    633                                 ldb_asprintf_errstring(ldb, "attribute %s on %s speicified, but with 0 values (illigal)",
    634                                                   el->name, ldb_dn_get_linearized(msg->dn));
    635                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    636                         }
    637728                        if (idx == -1) {
    638                                 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
    639                                         if (el->num_values > 1) {
    640                                                 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
    641                                                                el->name, ldb_dn_get_linearized(msg->dn));
    642                                                 return LDB_ERR_CONSTRAINT_VIOLATION;
     729                                if (ltdb_msg_add_element(ldb, msg2, el) != 0) {
     730                                        ret = LDB_ERR_OTHER;
     731                                        goto done;
     732                                }
     733                                ret = ltdb_index_add_element(module, msg2->dn,
     734                                                             el);
     735                                if (ret != LDB_SUCCESS) {
     736                                        goto done;
     737                                }
     738                        } else {
     739                                j = (unsigned int) idx;
     740                                el2 = &(msg2->elements[j]);
     741
     742                                /* We cannot add another value on a existing one
     743                                   if the attribute is single-valued */
     744                                if (ldb_tdb_single_valued(a, el)) {
     745                                        ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
     746                                                               el->name, ldb_dn_get_linearized(msg2->dn));
     747                                        ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     748                                        goto done;
     749                                }
     750
     751                                /* Check that values don't exist yet on multi-
     752                                   valued attributes or aren't provided twice */
     753                                for (j = 0; j < el->num_values; j++) {
     754                                        if (ldb_msg_find_val(el2, &el->values[j]) != NULL) {
     755                                                if (control_permissive) {
     756                                                        /* remove this one as if it was never added */
     757                                                        el->num_values--;
     758                                                        for (k = j; k < el->num_values; k++) {
     759                                                                el->values[k] = el->values[k + 1];
     760                                                        }
     761                                                        j--; /* rewind */
     762
     763                                                        continue;
     764                                                }
     765
     766                                                ldb_asprintf_errstring(ldb,
     767                                                                       "attribute '%s': value #%u on '%s' already exists",
     768                                                                       el->name, j, ldb_dn_get_linearized(msg2->dn));
     769                                                ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     770                                                goto done;
     771                                        }
     772                                        if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
     773                                                ldb_asprintf_errstring(ldb,
     774                                                                       "attribute '%s': value #%u on '%s' provided more than once",
     775                                                                       el->name, j, ldb_dn_get_linearized(msg2->dn));
     776                                                ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     777                                                goto done;
    643778                                        }
    644779                                }
    645                                 if (msg_add_element(ldb, msg2, el) != 0) {
     780
     781                                /* Now combine existing and new values to a new
     782                                   attribute record */
     783                                vals = talloc_realloc(msg2->elements,
     784                                                      el2->values, struct ldb_val,
     785                                                      el2->num_values + el->num_values);
     786                                if (vals == NULL) {
     787                                        ldb_oom(ldb);
    646788                                        ret = LDB_ERR_OTHER;
    647                                         goto failed;
     789                                        goto done;
    648790                                }
    649                                 continue;
    650                         }
    651 
    652                         /* If this is an add, then if it already
    653                          * exists in the object, then we violoate the
    654                          * single-value rule */
    655                         if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
    656                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    657                         }
    658 
    659                         el2 = &msg2->elements[idx];
    660 
    661                         /* An attribute with this name already exists,
    662                          * add all values if they don't already exist
    663                          * (check both the other elements to be added,
    664                          * and those already in the db). */
    665 
    666                         for (j=0;j<el->num_values;j++) {
    667                                 if (ldb_msg_find_val(el2, &el->values[j])) {
    668                                         ldb_asprintf_errstring(ldb, "%s: value #%d already exists", el->name, j);
    669                                         ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
    670                                         goto failed;
     791
     792                                for (j=0; j<el->num_values; j++) {
     793                                        vals[el2->num_values + j] =
     794                                                ldb_val_dup(vals, &el->values[j]);
    671795                                }
    672                                 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
    673                                         ldb_asprintf_errstring(ldb, "%s: value #%d provided more than once", el->name, j);
    674                                         ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
    675                                         goto failed;
     796
     797                                el2->values = vals;
     798                                el2->num_values += el->num_values;
     799
     800                                ret = ltdb_index_add_element(module, msg2->dn, el);
     801                                if (ret != LDB_SUCCESS) {
     802                                        goto done;
    676803                                }
    677804                        }
    678805
    679                         vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
    680                                                 el2->num_values + el->num_values);
    681 
    682                         if (vals == NULL) {
    683                                 ret = LDB_ERR_OTHER;
    684                                 goto failed;
     806                        break;
     807
     808                case LDB_FLAG_MOD_REPLACE:
     809
     810                        if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) {
     811                                ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
     812                                                       el->name, ldb_dn_get_linearized(msg2->dn));
     813                                ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     814                                goto done;
    685815                        }
    686816
    687                         for (j=0;j<el->num_values;j++) {
    688                                 vals[el2->num_values + j] =
    689                                         ldb_val_dup(vals, &el->values[j]);
    690                         }
    691 
    692                         el2->values = vals;
    693                         el2->num_values += el->num_values;
    694 
    695                         break;
    696 
    697                 case LDB_FLAG_MOD_REPLACE:
    698                         if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
    699                                 if (el->num_values > 1) {
    700                                         ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
    701                                                                el->name, ldb_dn_get_linearized(msg->dn));
    702                                         return LDB_ERR_CONSTRAINT_VIOLATION;
     817                        /* TODO: This is O(n^2) - replace with more efficient check */
     818                        for (j=0; j<el->num_values; j++) {
     819                                if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
     820                                        ldb_asprintf_errstring(ldb,
     821                                                               "attribute '%s': value #%u on '%s' provided more than once",
     822                                                               el->name, j, ldb_dn_get_linearized(msg2->dn));
     823                                        ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     824                                        goto done;
    703825                                }
    704826                        }
    705                         /* replace all elements of this attribute name with the elements
    706                            listed. The attribute not existing is not an error */
    707                         msg_delete_attribute(module, ldb, msg2, el->name);
    708 
    709                         for (j=0;j<el->num_values;j++) {
    710                                 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
    711                                         ldb_asprintf_errstring(ldb, "%s: value #%d provided more than once", el->name, j);
    712                                         ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
    713                                         goto failed;
     827
     828                        /* Checks if element already exists */
     829                        idx = find_element(msg2, el->name);
     830                        if (idx != -1) {
     831                                j = (unsigned int) idx;
     832                                el2 = &(msg2->elements[j]);
     833                                if (ldb_msg_element_compare(el, el2) == 0) {
     834                                        /* we are replacing with the same values */
     835                                        continue;
     836                                }
     837                       
     838                                /* Delete the attribute if it exists in the DB */
     839                                if (msg_delete_attribute(module, ldb, msg2,
     840                                                         el->name) != 0) {
     841                                        ret = LDB_ERR_OTHER;
     842                                        goto done;
    714843                                }
    715844                        }
    716845
    717                         /* add the replacement element, if not empty */
    718                         if (el->num_values != 0 &&
    719                             msg_add_element(ldb, msg2, el) != 0) {
     846                        /* Recreate it with the new values */
     847                        if (ltdb_msg_add_element(ldb, msg2, el) != 0) {
    720848                                ret = LDB_ERR_OTHER;
    721                                 goto failed;
     849                                goto done;
    722850                        }
     851
     852                        ret = ltdb_index_add_element(module, msg2->dn, el);
     853                        if (ret != LDB_SUCCESS) {
     854                                goto done;
     855                        }
     856
    723857                        break;
    724858
    725859                case LDB_FLAG_MOD_DELETE:
    726 
    727                         dn = ldb_dn_get_linearized(msg->dn);
     860                        dn = ldb_dn_get_linearized(msg2->dn);
    728861                        if (dn == NULL) {
    729862                                ret = LDB_ERR_OTHER;
    730                                 goto failed;
     863                                goto done;
    731864                        }
    732865
    733                         /* we could be being asked to delete all
    734                            values or just some values */
    735866                        if (msg->elements[i].num_values == 0) {
    736                                 if (msg_delete_attribute(module, ldb, msg2,
    737                                                          msg->elements[i].name) != 0) {
    738                                         ldb_asprintf_errstring(ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
    739                                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
    740                                         goto failed;
     867                                /* Delete the whole attribute */
     868                                ret = msg_delete_attribute(module, ldb, msg2,
     869                                                           msg->elements[i].name);
     870                                if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE &&
     871                                    control_permissive) {
     872                                        ret = LDB_SUCCESS;
     873                                } else {
     874                                        ldb_asprintf_errstring(ldb,
     875                                                               "attribute '%s': no such attribute for delete on '%s'",
     876                                                               msg->elements[i].name, dn);
    741877                                }
    742                                 break;
    743                         }
    744                         for (j=0;j<msg->elements[i].num_values;j++) {
    745                                 if (msg_delete_element(module,
    746                                                        msg2,
    747                                                        msg->elements[i].name,
    748                                                        &msg->elements[i].values[j]) != 0) {
    749                                         ldb_asprintf_errstring(ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
    750                                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
    751                                         goto failed;
     878                                if (ret != LDB_SUCCESS) {
     879                                        goto done;
    752880                                }
    753                                 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
    754                                 if (ret != LDB_SUCCESS) {
    755                                         goto failed;
     881                        } else {
     882                                /* Delete specified values from an attribute */
     883                                for (j=0; j < msg->elements[i].num_values; j++) {
     884                                        ret = msg_delete_element(module,
     885                                                                 msg2,
     886                                                                 msg->elements[i].name,
     887                                                                 &msg->elements[i].values[j]);
     888                                        if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE &&
     889                                            control_permissive) {
     890                                                ret = LDB_SUCCESS;
     891                                        } else {
     892                                                ldb_asprintf_errstring(ldb,
     893                                                                       "attribute '%s': no matching attribute value while deleting attribute on '%s'",
     894                                                                       msg->elements[i].name, dn);
     895                                        }
     896                                        if (ret != LDB_SUCCESS) {
     897                                                goto done;
     898                                        }
    756899                                }
    757900                        }
     
    759902                default:
    760903                        ldb_asprintf_errstring(ldb,
    761                                 "Invalid ldb_modify flags on %s: 0x%x",
    762                                 msg->elements[i].name,
    763                                 msg->elements[i].flags & LDB_FLAG_MOD_MASK);
     904                                               "attribute '%s': invalid modify flags on '%s': 0x%x",
     905                                               msg->elements[i].name, ldb_dn_get_linearized(msg->dn),
     906                                               msg->elements[i].flags & LDB_FLAG_MOD_MASK);
    764907                        ret = LDB_ERR_PROTOCOL_ERROR;
    765                         goto failed;
     908                        goto done;
    766909                }
    767910        }
    768911
    769         /* we've made all the mods
    770          * save the modified record back into the database */
    771912        ret = ltdb_store(module, msg2, TDB_MODIFY);
    772913        if (ret != LDB_SUCCESS) {
    773                 goto failed;
    774         }
    775 
    776         ret = ltdb_modified(module, msg->dn);
     914                goto done;
     915        }
     916
     917        ret = ltdb_modified(module, msg2->dn);
    777918        if (ret != LDB_SUCCESS) {
    778                 goto failed;
    779         }
    780 
     919                goto done;
     920        }
     921
     922done:
    781923        talloc_free(tdb_key.dptr);
    782         free(tdb_data.dptr);
    783         return ret;
    784 
    785 failed:
    786         talloc_free(tdb_key.dptr);
    787         free(tdb_data.dptr);
    788924        return ret;
    789925}
     
    796932        struct ldb_module *module = ctx->module;
    797933        struct ldb_request *req = ctx->req;
    798         int tret;
     934        int ret = LDB_SUCCESS;
     935
     936        ret = ltdb_check_special_dn(module, req->op.mod.message);
     937        if (ret != LDB_SUCCESS) {
     938                return ret;
     939        }
    799940
    800941        ldb_request_set_state(req, LDB_ASYNC_PENDING);
    801942
    802         tret = ltdb_check_special_dn(module, req->op.mod.message);
    803         if (tret != LDB_SUCCESS) {
    804                 return tret;
    805         }
    806 
    807943        if (ltdb_cache_load(module) != 0) {
    808944                return LDB_ERR_OPERATIONS_ERROR;
    809945        }
    810946
    811         tret = ltdb_modify_internal(module, req->op.mod.message);
    812         if (tret != LDB_SUCCESS) {
    813                 return tret;
    814         }
    815 
    816         return LDB_SUCCESS;
     947        ret = ltdb_modify_internal(module, req->op.mod.message, req);
     948
     949        return ret;
    817950}
    818951
     
    825958        struct ldb_request *req = ctx->req;
    826959        struct ldb_message *msg;
    827         int tret;
     960        int ret = LDB_SUCCESS;
    828961
    829962        ldb_request_set_state(req, LDB_ASYNC_PENDING);
     
    833966        }
    834967
    835         msg = talloc(ctx, struct ldb_message);
     968        msg = ldb_msg_new(ctx);
    836969        if (msg == NULL) {
    837970                return LDB_ERR_OPERATIONS_ERROR;
     
    840973        /* in case any attribute of the message was indexed, we need
    841974           to fetch the old record */
    842         tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
    843         if (tret != LDB_SUCCESS) {
     975        ret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
     976        if (ret != LDB_SUCCESS) {
    844977                /* not finding the old record is an error */
    845                 return tret;
    846         }
    847 
    848         msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
    849         if (!msg->dn) {
    850                 return LDB_ERR_OPERATIONS_ERROR;
     978                return ret;
    851979        }
    852980
     
    855983         * atomic
    856984         */
    857         tret = ltdb_delete_internal(module, req->op.rename.olddn);
    858         if (tret != LDB_SUCCESS) {
    859                 return tret;
    860         }
    861 
    862         tret = ltdb_add_internal(module, msg);
    863         if (tret != LDB_SUCCESS) {
    864                 return tret;
    865         }
    866 
    867         return LDB_SUCCESS;
     985        ret = ltdb_delete_internal(module, msg->dn);
     986        if (ret != LDB_SUCCESS) {
     987                return ret;
     988        }
     989
     990        msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
     991        if (msg->dn == NULL) {
     992                return LDB_ERR_OPERATIONS_ERROR;
     993        }
     994
     995        ret = ltdb_add_internal(module, msg);
     996
     997        return ret;
    868998}
    869999
     
    9591089        struct ldb_module *module = ctx->module;
    9601090        struct ldb_request *req = ctx->req;
    961         TALLOC_CTX *tmp_ctx;
     1091        TALLOC_CTX *tmp_ctx = NULL;
    9621092        struct ldb_seqnum_request *seq;
    9631093        struct ldb_seqnum_result *res;
     
    9651095        struct ldb_dn *dn;
    9661096        const char *date;
    967         int ret;
     1097        int ret = LDB_SUCCESS;
    9681098
    9691099        ldb = ldb_module_get_ctx(module);
     
    9861116                goto done;
    9871117        }
     1118
    9881119        tmp_ctx = talloc_new(req);
    9891120        if (tmp_ctx == NULL) {
     
    9931124
    9941125        dn = ldb_dn_new(tmp_ctx, ldb, LTDB_BASEINFO);
    995 
    996         msg = talloc(tmp_ctx, struct ldb_message);
     1126        if (dn == NULL) {
     1127                ret = LDB_ERR_OPERATIONS_ERROR;
     1128                goto done;
     1129        }
     1130
     1131        msg = ldb_msg_new(tmp_ctx);
    9971132        if (msg == NULL) {
    9981133                ret = LDB_ERR_OPERATIONS_ERROR;
     
    10311166        (*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
    10321167        (*ext)->data = talloc_steal(*ext, res);
    1033 
    1034         ret = LDB_SUCCESS;
    10351168
    10361169done:
     
    11671300        default:
    11681301                /* no other op supported */
    1169                 ret = LDB_ERR_UNWILLING_TO_PERFORM;
     1302                ret = LDB_ERR_PROTOCOL_ERROR;
    11701303        }
    11711304
     
    11971330                               struct ldb_request *req)
    11981331{
     1332        struct ldb_control *control_permissive;
    11991333        struct ldb_context *ldb;
    12001334        struct tevent_context *ev;
     
    12021336        struct tevent_timer *te;
    12031337        struct timeval tv;
    1204 
    1205         if (check_critical_controls(req->controls)) {
    1206                 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
    1207         }
     1338        unsigned int i;
    12081339
    12091340        ldb = ldb_module_get_ctx(module);
     1341
     1342        control_permissive = ldb_request_get_control(req,
     1343                                        LDB_CONTROL_PERMISSIVE_MODIFY_OID);
     1344
     1345        for (i = 0; req->controls && req->controls[i]; i++) {
     1346                if (req->controls[i]->critical &&
     1347                    req->controls[i] != control_permissive) {
     1348                        ldb_asprintf_errstring(ldb, "Unsupported critical extension %s",
     1349                                               req->controls[i]->oid);
     1350                        return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
     1351                }
     1352        }
    12101353
    12111354        if (req->starttime == 0 || req->timeout == 0) {
     
    12181361        ac = talloc_zero(ldb, struct ltdb_context);
    12191362        if (ac == NULL) {
    1220                 ldb_set_errstring(ldb, "Out of Memory");
     1363                ldb_oom(ldb);
    12211364                return LDB_ERR_OPERATIONS_ERROR;
    12221365        }
     
    12541397}
    12551398
     1399static int ltdb_init_rootdse(struct ldb_module *module)
     1400{
     1401        struct ldb_context *ldb;
     1402        int ret;
     1403
     1404        ldb = ldb_module_get_ctx(module);
     1405
     1406        ret = ldb_mod_register_control(module,
     1407                                       LDB_CONTROL_PERMISSIVE_MODIFY_OID);
     1408        /* ignore errors on this - we expect it for non-sam databases */
     1409
     1410        /* there can be no module beyond the backend, just return */
     1411        return LDB_SUCCESS;
     1412}
     1413
    12561414static const struct ldb_module_ops ltdb_ops = {
    12571415        .name              = "tdb",
     1416        .init_context      = ltdb_init_rootdse,
    12581417        .search            = ltdb_handle_request,
    12591418        .add               = ltdb_handle_request,
     
    12851444                        ldb_debug(ldb, LDB_DEBUG_ERROR,
    12861445                                  "Invalid tdb URL '%s'", url);
    1287                         return -1;
     1446                        return LDB_ERR_OPERATIONS_ERROR;
    12881447                }
    12891448                path = url+6;
     
    13131472        if (!ltdb) {
    13141473                ldb_oom(ldb);
    1315                 return -1;
     1474                return LDB_ERR_OPERATIONS_ERROR;
    13161475        }
    13171476
     
    13241483                          "Unable to open tdb '%s'", path);
    13251484                talloc_free(ltdb);
    1326                 return -1;
     1485                return LDB_ERR_OPERATIONS_ERROR;
     1486        }
     1487
     1488        if (getenv("LDB_WARN_UNINDEXED")) {
     1489                ltdb->warn_unindexed = true;
    13271490        }
    13281491
     
    13321495        if (!module) {
    13331496                talloc_free(ltdb);
    1334                 return -1;
     1497                return LDB_ERR_OPERATIONS_ERROR;
    13351498        }
    13361499        ldb_module_set_private(module, ltdb);
     1500        talloc_steal(module, ltdb);
    13371501
    13381502        if (ltdb_cache_load(module) != 0) {
    13391503                talloc_free(module);
    13401504                talloc_free(ltdb);
    1341                 return -1;
     1505                return LDB_ERR_OPERATIONS_ERROR;
    13421506        }
    13431507
    13441508        *_module = module;
    1345         return 0;
    1346 }
    1347 
    1348 const struct ldb_backend_ops ldb_tdb_backend_ops = {
    1349         .name = "tdb",
    1350         .connect_fn = ltdb_connect
    1351 };
     1509        return LDB_SUCCESS;
     1510}
     1511
     1512int ldb_tdb_init(const char *version)
     1513{
     1514        LDB_MODULE_CHECK_VERSION(version);
     1515        return ldb_register_backend("tdb", ltdb_connect, false);
     1516}
  • trunk/server/source4/lib/ldb/ldb_tdb/ldb_tdb.h

    r414 r745  
    1 #include "ldb_includes.h"
     1#include "replace.h"
     2#include "system/filesys.h"
     3#include "system/time.h"
    24#include "tdb.h"
    35#include "ldb_module.h"
     
    1820                struct ldb_message *indexlist;
    1921                struct ldb_message *attributes;
     22                bool one_level_indexes;
     23                bool attribute_indexes;
    2024
    2125                struct {
     
    3034        struct ltdb_idxptr *idxptr;
    3135        bool prepared_commit;
     36        int read_lock_count;
     37
     38        bool warn_unindexed;
    3239};
    3340
     
    5966#define LTDB_INDEXLIST  "@INDEXLIST"
    6067#define LTDB_IDX        "@IDX"
    61 #define LTDB_IDXPTR     "@IDXPTR"
     68#define LTDB_IDXVERSION "@IDXVERSION"
    6269#define LTDB_IDXATTR    "@IDXATTR"
    6370#define LTDB_IDXONE     "@IDXONE"
     
    8491
    8592int ltdb_search_indexed(struct ltdb_context *ctx, uint32_t *);
    86 int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg);
    87 int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg);
    88 int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add);
     93int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg);
     94int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg);
     95int ltdb_index_del_element(struct ldb_module *module, struct ldb_dn *dn,
     96                           struct ldb_message_element *el);
     97int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
     98                           struct ldb_message_element *el);
     99int ltdb_index_del_value(struct ldb_module *module, struct ldb_dn *dn,
     100                         struct ldb_message_element *el, unsigned int v_idx);
    89101int ltdb_reindex(struct ldb_module *module);
    90102int ltdb_index_transaction_start(struct ldb_module *module);
     
    123135struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn);
    124136int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs);
     137int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg, struct ldb_request *req);
    125138int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn);
    126 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg);
    127 
    128 int ltdb_index_del_value(struct ldb_module *module, const char *dn,
    129                          struct ldb_message_element *el, int v_idx);
     139int ltdb_err_map(enum TDB_ERROR tdb_code);
    130140
    131141struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx,
  • trunk/server/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c

    r414 r745  
    2323
    2424#include "ldb_tdb.h"
     25#include "dlinklist.h"
    2526
    2627/*
     
    4344{
    4445        tdb_close(w->tdb);
    45         if (w->next) {
    46                 w->next->prev = w->prev;
    47         }
    48         if (w->prev) {
    49                 w->prev->next = w->next;
    50         }
    51         if (w == tdb_list) {
    52                 tdb_list = w->next;
    53         }
     46        DLIST_REMOVE(tdb_list, w);
    5447        return 0;
    5548}                               
     
    144137        talloc_set_destructor(w, ltdb_wrap_destructor);
    145138
    146         w->next = tdb_list;
    147         w->prev = NULL;
    148         if (tdb_list) {
    149                 tdb_list->prev = w;
    150         }
    151         tdb_list = w;
     139        DLIST_ADD(tdb_list, w);
    152140       
    153141        return w->tdb;
  • trunk/server/source4/lib/ldb/man/ldbadd.1.xml

    r414 r745  
    2828        <title>DESCRIPTION</title>
    2929
    30         <para>ldbadd adds records to an ldb(7) database. It reads
     30        <para>ldbadd adds records to an ldb(3) database. It reads
    3131                the ldif(5) files specified on the command line and adds
    3232                the records from these files to the LDB database, which is specified
     
    5353                        <term>-H &lt;ldb-url&gt;</term>
    5454                        <listitem><para>
    55                                 LDB URL to connect to. See ldb(7) for details.
     55                                LDB URL to connect to. See ldb(3) for details.
    5656                        </para></listitem>
    5757                </varlistentry>
     
    8282        <title>SEE ALSO</title>
    8383
    84         <para>ldb(7), ldbmodify, ldbdel, ldif(5)</para>
     84        <para>ldb(3), ldbmodify, ldbdel, ldif(5)</para>
    8585
    8686</refsect1>
  • trunk/server/source4/lib/ldb/man/ldbdel.1.xml

    r414 r745  
    2727        <title>DESCRIPTION</title>
    2828
    29         <para>ldbdel deletes records from an ldb(7) database.
     29        <para>ldbdel deletes records from an ldb(3) database.
    3030                It deletes the records identified by the dn's specified
    3131                on the command-line. </para>
     
    5151                        <term>-H &lt;ldb-url&gt;</term>
    5252                        <listitem><para>
    53                                 LDB URL to connect to. See ldb(7) for details.
     53                                LDB URL to connect to. See ldb(3) for details.
    5454                        </para></listitem>
    5555                </varlistentry>
     
    8080        <title>SEE ALSO</title>
    8181
    82         <para>ldb(7), ldbmodify, ldbadd, ldif(5)</para>
     82        <para>ldb(3), ldbmodify, ldbadd, ldif(5)</para>
    8383
    8484</refsect1>
  • trunk/server/source4/lib/ldb/man/ldbedit.1.xml

    r414 r745  
    173173        <title>SEE ALSO</title>
    174174       
    175         <para>ldb(7), ldbmodify(1), ldbdel(1), ldif(5), vi(1)</para>
     175        <para>ldb(3), ldbmodify(1), ldbdel(1), ldif(5), vi(1)</para>
    176176
    177177    </refsect1>
  • trunk/server/source4/lib/ldb/man/ldbmodify.1.xml

    r414 r745  
    4343                        <term>-H &lt;ldb-url&gt;</term>
    4444                        <listitem><para>
    45                                 LDB URL to connect to. See ldb(7) for details.
     45                                LDB URL to connect to. See ldb(3) for details.
    4646                        </para></listitem>
    4747                </varlistentry>
     
    7070        <title>SEE ALSO</title>
    7171
    72         <para>ldb(7), ldbedit</para>
     72        <para>ldb(3), ldbedit</para>
    7373
    7474</refsect1>
  • trunk/server/source4/lib/ldb/man/ldbrename.1.xml

    r414 r745  
    4949                        <term>-H &lt;ldb-url&gt;</term>
    5050                        <listitem><para>
    51                                 LDB URL to connect to. See ldb(7) for details.
     51                                LDB URL to connect to. See ldb(3) for details.
    5252                        </para></listitem>
    5353                </varlistentry>
     
    8484        <title>SEE ALSO</title>
    8585
    86         <para>ldb(7), ldbmodify, ldbdel, ldif(5)</para>
     86        <para>ldb(3), ldbmodify, ldbdel, ldif(5)</para>
    8787
    8888</refsect1>
  • trunk/server/source4/lib/ldb/man/ldbsearch.1.xml

    r414 r745  
    5252                        <term>-H &lt;ldb-url&gt;</term>
    5353                        <listitem><para>
    54                                 LDB URL to connect to. See ldb(7) for details.
     54                                LDB URL to connect to. See ldb(3) for details.
    5555                        </para></listitem>
    5656                </varlistentry>
     
    9696        <title>SEE ALSO</title>
    9797
    98         <para>ldb(7), ldbedit(1)</para>
     98        <para>ldb(3), ldbedit(1)</para>
    9999
    100100</refsect1>
  • trunk/server/source4/lib/ldb/modules/asq.c

    r414 r745  
    3333 */
    3434
     35#include "replace.h"
     36#include "system/filesys.h"
     37#include "system/time.h"
    3538#include "ldb_module.h"
    3639
     
    5659
    5760        struct ldb_request **reqs;
    58         int num_reqs;
    59         int cur_req;
     61        unsigned int num_reqs;
     62        unsigned int cur_req;
    6063
    6164        struct ldb_control **controls;
     
    8689{
    8790        struct ldb_asq_control *asq;
    88         int i;
     91        unsigned int i;
    8992
    9093        if (ac->controls) {
     
    238241                                        ac->req);
    239242        if (ret != LDB_SUCCESS) {
    240                 return LDB_ERR_OPERATIONS_ERROR;
     243                return ret;
    241244        }
    242245
     
    251254        struct ldb_dn *dn;
    252255        struct ldb_message_element *el;
    253         int ret, i;
     256        unsigned int i;
     257        int ret;
    254258
    255259        if (ac->base_res == NULL) {
     
    293297                                                ac->req);
    294298                if (ret != LDB_SUCCESS) {
    295                         return LDB_ERR_OPERATIONS_ERROR;
     299                        return ret;
    296300                }
    297301
    298302                /* remove the ASQ control itself */
    299303                control = ldb_request_get_control(ac->req, LDB_CONTROL_ASQ_OID);
    300                 if (!save_controls(control, ac->reqs[i], &saved_controls)) {
     304                if (!ldb_save_controls(control, ac->reqs[i], &saved_controls)) {
    301305                        return LDB_ERR_OPERATIONS_ERROR;
    302306                }
     
    400404}
    401405
    402 const struct ldb_module_ops ldb_asq_module_ops = {
     406static const struct ldb_module_ops ldb_asq_module_ops = {
    403407        .name              = "asq",
    404408        .search            = asq_search,
    405409        .init_context      = asq_init
    406410};
     411
     412int ldb_asq_init(const char *version)
     413{
     414        LDB_MODULE_CHECK_VERSION(version);
     415        return ldb_register_module(&ldb_asq_module_ops);
     416}
  • trunk/server/source4/lib/ldb/modules/paged_results.c

    r414 r745  
    3333 */
    3434
    35 #include "ldb_includes.h"
     35#include "replace.h"
     36#include "system/filesys.h"
     37#include "system/time.h"
    3638#include "ldb_module.h"
    3739
     
    6668
    6769struct private_data {
    68 
    69         int next_free_id;
     70        unsigned int next_free_id;
    7071        struct results_store *store;
    7172       
     
    9697{
    9798        struct results_store *newr;
    98         int new_id = priv->next_free_id++;
     99        unsigned int new_id = priv->next_free_id++;
    99100
    100101        /* TODO: we should have a limit on the number of
     
    141142        struct ldb_paged_control *paged;
    142143        struct message_store *msg;
    143         int i, num_ctrls, ret;
     144        unsigned int i, num_ctrls;
     145        int ret;
    144146
    145147        if (ac->store == NULL) {
     
    327329        ac->req = req;
    328330        ac->size = paged_ctrl->size;
     331        if (ac->size < 0) {
     332                /* apparently some clients send more than 2^31. This
     333                   violates the ldap standard, but we need to cope */
     334                ac->size = 0x7FFFFFFF;
     335        }
    329336
    330337        /* check if it is a continuation search the store */
     
    348355                                                paged_search_callback,
    349356                                                req);
     357                if (ret != LDB_SUCCESS) {
     358                        return ret;
     359                }
    350360
    351361                /* save it locally and remove it from the list */
    352362                /* we do not need to replace them later as we
    353363                 * are keeping the original req intact */
    354                 if (!save_controls(control, search_req, &saved_controls)) {
     364                if (!ldb_save_controls(control, search_req, &saved_controls)) {
    355365                        return LDB_ERR_OPERATIONS_ERROR;
    356366                }
     
    416426}
    417427
    418 const struct ldb_module_ops ldb_paged_results_module_ops = {
     428static const struct ldb_module_ops ldb_paged_results_module_ops = {
    419429        .name           = "paged_results",
    420430        .search         = paged_search,
    421431        .init_context   = paged_request_init
    422432};
     433
     434int ldb_paged_results_init(const char *version)
     435{
     436        LDB_MODULE_CHECK_VERSION(version);
     437        return ldb_register_module(&ldb_paged_results_module_ops);
     438}
  • trunk/server/source4/lib/ldb/modules/paged_searches.c

    r414 r745  
    3434 */
    3535
    36 #include "includes.h"
     36#include "replace.h"
     37#include "system/filesys.h"
     38#include "system/time.h"
    3739#include "ldb_module.h"
    3840
     
    5355
    5456        char **saved_referrals;
    55         int num_referrals;
     57        unsigned int num_referrals;
    5658
    5759        struct ldb_request *down_req;
     
    7981                        return LDB_ERR_OPERATIONS_ERROR;
    8082                } else {
    81                         /* No cookie recived yet, valid to just return the full data set */
     83                        /* No cookie received yet, valid to just return the full data set */
    8284
    8385                        /* we are done */
     
    133135        struct ldb_reply *ares;
    134136        int ret;
    135         int i;
     137        unsigned int i;
    136138
    137139        for (i = 0; i < ac->num_referrals; i++) {
     
    271273                                        ps_callback,
    272274                                        ac->req);
     275        LDB_REQ_SET_LOCATION(ac->down_req);
    273276        if (ret != LDB_SUCCESS) {
    274277                return ret;
     
    352355                                   data, check_supported_paged,
    353356                                   NULL);
     357        LDB_REQ_SET_LOCATION(req);
    354358        if (ret != LDB_SUCCESS) {
    355359                return ret;
     
    370374}
    371375
    372 _PUBLIC_ const struct ldb_module_ops ldb_paged_searches_module_ops = {
     376static const struct ldb_module_ops ldb_paged_searches_module_ops = {
    373377        .name           = "paged_searches",
    374378        .search         = ps_search,
    375379        .init_context   = ps_init
    376380};
     381
     382int ldb_paged_searches_init(const char *version)
     383{
     384        LDB_MODULE_CHECK_VERSION(version);
     385        return ldb_register_module(&ldb_paged_searches_module_ops);
     386}
  • trunk/server/source4/lib/ldb/modules/rdn_name.c

    r414 r745  
    22   ldb database library
    33
    4    Copyright (C) Andrew Bartlett 2005
     4   Copyright (C) Andrew Bartlett 2005-2009
    55   Copyright (C) Simo Sorce 2006-2008
    66
     
    3737 */
    3838
    39 #include "ldb_includes.h"
     39#include "replace.h"
     40#include "system/filesys.h"
     41#include "system/time.h"
    4042#include "ldb_module.h"
    4143
    4244struct rename_context {
    43 
    4445        struct ldb_module *module;
    4546        struct ldb_request *req;
     
    4748        struct ldb_reply *ares;
    4849};
    49 
    50 static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
    51 {
    52         int i;
    53 
    54         for (i = 0; i < msg->num_elements; i++) {
    55                 if (ldb_attr_cmp(name, msg->elements[i].name) == 0) {
    56                         return &msg->elements[i];
    57                 }
    58         }
    59 
    60         return NULL;
    61 }
    6250
    6351static int rdn_name_add_callback(struct ldb_request *req,
     
    7260                                        LDB_ERR_OPERATIONS_ERROR);
    7361        }
     62
     63        if (ares->type == LDB_REPLY_REFERRAL) {
     64                return ldb_module_send_referral(ac->req, ares->referral);
     65        }
     66
    7467        if (ares->error != LDB_SUCCESS) {
    7568                return ldb_module_done(ac->req, ares->controls,
     
    9588        const struct ldb_schema_attribute *a;
    9689        const char *rdn_name;
     90        const struct ldb_val *rdn_val_p;
    9791        struct ldb_val rdn_val;
    98         int i, ret;
     92        unsigned int i;
     93        int ret;
    9994
    10095        ldb = ldb_module_get_ctx(module);
    101         ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_add_record");
    10296
    10397        /* do not manipulate our control entries */
     
    121115        rdn_name = ldb_dn_get_rdn_name(msg->dn);
    122116        if (rdn_name == NULL) {
    123                 talloc_free(ac);
    124117                return LDB_ERR_OPERATIONS_ERROR;
    125118        }
    126119       
    127         rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(msg->dn));
    128        
    129         /* Perhaps someone above us tried to set this? */
    130         if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
    131                 attribute->num_values = 0;
    132         }
    133 
    134         if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
    135                 talloc_free(ac);
    136                 return LDB_ERR_OPERATIONS_ERROR;
    137         }
    138 
    139         attribute = rdn_name_find_attribute(msg, rdn_name);
    140 
     120        rdn_val_p = ldb_dn_get_rdn_val(msg->dn);
     121        if (rdn_val_p == NULL) {
     122                return LDB_ERR_OPERATIONS_ERROR;
     123        }
     124        if (rdn_val_p->length == 0) {
     125                ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!",
     126                                       ldb_dn_get_linearized(req->op.add.message->dn));
     127                return LDB_ERR_INVALID_DN_SYNTAX;
     128        }
     129        rdn_val = ldb_val_dup(msg, rdn_val_p);
     130
     131        /* Perhaps someone above us tried to set this? Then ignore it */
     132        ldb_msg_remove_attr(msg, "name");
     133
     134        ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL);
     135        if (ret != LDB_SUCCESS) {
     136                return ret;
     137        }
     138
     139        a = ldb_schema_attribute_by_name(ldb, rdn_name);
     140        if (a == NULL) {
     141                return LDB_ERR_OPERATIONS_ERROR;
     142        }
     143
     144        attribute = ldb_msg_find_element(msg, rdn_name);
    141145        if (!attribute) {
    142                 if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
    143                         talloc_free(ac);
    144                         return LDB_ERR_OPERATIONS_ERROR;
     146                /* add entry with normalised RDN information if possible */
     147                if (a->name != NULL) {
     148                        ret = ldb_msg_add_value(msg, a->name, &rdn_val, NULL);
     149                } else {
     150                        ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL);
     151                }
     152                if (ret != LDB_SUCCESS) {
     153                        return ret;
    145154                }
    146155        } else {
    147                 a = ldb_schema_attribute_by_name(ldb, rdn_name);
    148 
     156                /* normalise attribute name if possible */
     157                if (a->name != NULL) {
     158                        attribute->name = a->name;
     159                }
     160                /* normalise attribute value */
    149161                for (i = 0; i < attribute->num_values; i++) {
    150                         ret = a->syntax->comparison_fn(ldb, msg,
    151                                         &rdn_val, &attribute->values[i]);
    152                         if (ret == 0) {
     162                        bool matched;
     163                        if (a->syntax->operator_fn) {
     164                                ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
     165                                                             &rdn_val, &attribute->values[i], &matched);
     166                                if (ret != LDB_SUCCESS) return ret;
     167                        } else {
     168                                matched = (a->syntax->comparison_fn(ldb, msg,
     169                                                                    &rdn_val, &attribute->values[i]) == 0);
     170                        }
     171                        if (matched) {
    153172                                /* overwrite so it matches in case */
    154173                                attribute->values[i] = rdn_val;
     
    157176                }
    158177                if (i == attribute->num_values) {
    159                         char *rdn_errstring = talloc_asprintf(ac, "RDN mismatch on %s: %s (%.*s) should match one of:",
    160                                                           ldb_dn_get_linearized(msg->dn), rdn_name,
    161                                                           (int)rdn_val.length, (const char *)rdn_val.data);
     178                        char *rdn_errstring = talloc_asprintf(ac,
     179                                "RDN mismatch on %s: %s (%.*s) should match one of:",
     180                                ldb_dn_get_linearized(msg->dn), rdn_name,
     181                                (int)rdn_val.length, (const char *)rdn_val.data);
    162182                        for (i = 0; i < attribute->num_values; i++) {
    163                                 rdn_errstring = talloc_asprintf_append(rdn_errstring, " (%.*s)",
    164                                                                        (int)attribute->values[i].length,
    165                                                                        (const char *)attribute->values[i].data);
     183                                rdn_errstring = talloc_asprintf_append(
     184                                        rdn_errstring, " (%.*s)",
     185                                        (int)attribute->values[i].length,
     186                                        (const char *)attribute->values[i].data);
    166187                        }
    167                         ldb_debug_set(ldb, LDB_DEBUG_FATAL, "%s", rdn_errstring);
    168                         talloc_free(ac);
     188                        ldb_set_errstring(ldb, rdn_errstring);
    169189                        /* Match AD's error here */
    170190                        return LDB_ERR_INVALID_DN_SYNTAX;
     
    197217                                        LDB_ERR_OPERATIONS_ERROR);
    198218        }
     219
     220        if (ares->type == LDB_REPLY_REFERRAL) {
     221                return ldb_module_send_referral(ac->req, ares->referral);
     222        }
     223
    199224        if (ares->error != LDB_SUCCESS) {
    200225                return ldb_module_done(ac->req, ares->controls,
     
    219244        struct ldb_request *mod_req;
    220245        const char *rdn_name;
     246        const struct ldb_val *rdn_val_p;
    221247        struct ldb_val rdn_val;
    222248        struct ldb_message *msg;
     
    229255                goto error;
    230256        }
     257
     258        if (ares->type == LDB_REPLY_REFERRAL) {
     259                return ldb_module_send_referral(ac->req, ares->referral);
     260        }
     261
    231262        if (ares->error != LDB_SUCCESS) {
    232263                return ldb_module_done(ac->req, ares->controls,
     
    250281                goto error;
    251282        }
     283
    252284        rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
    253285        if (rdn_name == NULL) {
    254286                goto error;
    255287        }
    256        
    257         rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(ac->req->op.rename.newdn));
    258        
     288
     289        rdn_val_p = ldb_dn_get_rdn_val(msg->dn);
     290        if (rdn_val_p == NULL) {
     291                goto error;
     292        }
     293        if (rdn_val_p->length == 0) {
     294                ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!",
     295                                       ldb_dn_get_linearized(req->op.rename.olddn));
     296                return ldb_module_done(ac->req, NULL, NULL,
     297                                       LDB_ERR_NAMING_VIOLATION);
     298        }
     299        rdn_val = ldb_val_dup(msg, rdn_val_p);
     300
    259301        if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
    260302                goto error;
     
    279321        talloc_steal(mod_req, msg);
    280322
    281         /* do the mod call */
    282         return ldb_request(ldb, mod_req);
     323        /* go on with the call chain */
     324        return ldb_next_request(ac->module, mod_req);
    283325
    284326error:
    285         return ldb_module_done(ac->req, NULL, NULL,
    286                                                 LDB_ERR_OPERATIONS_ERROR);
     327        return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
    287328}
    288329
     
    295336
    296337        ldb = ldb_module_get_ctx(module);
    297         ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_rename");
    298338
    299339        /* do not manipulate our control entries */
     
    321361
    322362        if (ret != LDB_SUCCESS) {
    323                 return LDB_ERR_OPERATIONS_ERROR;
     363                return ret;
    324364        }
    325365
     
    328368}
    329369
    330 const struct ldb_module_ops ldb_rdn_name_module_ops = {
     370static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
     371{
     372        struct ldb_context *ldb;
     373        const struct ldb_val *rdn_val_p;
     374
     375        ldb = ldb_module_get_ctx(module);
     376
     377        /* do not manipulate our control entries */
     378        if (ldb_dn_is_special(req->op.mod.message->dn)) {
     379                return ldb_next_request(module, req);
     380        }
     381
     382        rdn_val_p = ldb_dn_get_rdn_val(req->op.mod.message->dn);
     383        if (rdn_val_p == NULL) {
     384                return LDB_ERR_OPERATIONS_ERROR;
     385        }
     386        if (rdn_val_p->length == 0) {
     387                ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!",
     388                                       ldb_dn_get_linearized(req->op.mod.message->dn));
     389                return LDB_ERR_INVALID_DN_SYNTAX;
     390        }
     391
     392        if (ldb_msg_find_element(req->op.mod.message, "distinguishedName")) {
     393                ldb_asprintf_errstring(ldb, "Modify of 'distinguishedName' on %s not permitted, must use 'rename' operation instead",
     394                                       ldb_dn_get_linearized(req->op.mod.message->dn));
     395                return LDB_ERR_CONSTRAINT_VIOLATION;
     396        }
     397
     398        if (ldb_msg_find_element(req->op.mod.message, "name")) {
     399                ldb_asprintf_errstring(ldb, "Modify of 'name' on %s not permitted, must use 'rename' operation instead",
     400                                       ldb_dn_get_linearized(req->op.mod.message->dn));
     401                return LDB_ERR_NOT_ALLOWED_ON_RDN;
     402        }
     403
     404        if (ldb_msg_find_element(req->op.mod.message, ldb_dn_get_rdn_name(req->op.mod.message->dn))) {
     405                ldb_asprintf_errstring(ldb, "Modify of RDN '%s' on %s not permitted, must use 'rename' operation instead",
     406                                       ldb_dn_get_rdn_name(req->op.mod.message->dn), ldb_dn_get_linearized(req->op.mod.message->dn));
     407                return LDB_ERR_NOT_ALLOWED_ON_RDN;
     408        }
     409
     410        /* All OK, they kept their fingers out of the special attributes */
     411        return ldb_next_request(module, req);
     412}
     413
     414static int rdn_name_search(struct ldb_module *module, struct ldb_request *req)
     415{
     416        struct ldb_context *ldb;
     417        const char *rdn_name;
     418        const struct ldb_val *rdn_val_p;
     419
     420        ldb = ldb_module_get_ctx(module);
     421
     422        /* do not manipulate our control entries */
     423        if (ldb_dn_is_special(req->op.search.base)) {
     424                return ldb_next_request(module, req);
     425        }
     426
     427        rdn_name = ldb_dn_get_rdn_name(req->op.search.base);
     428        rdn_val_p = ldb_dn_get_rdn_val(req->op.search.base);
     429        if ((rdn_name != NULL) && (rdn_val_p == NULL)) {
     430                return LDB_ERR_OPERATIONS_ERROR;
     431        }
     432        if ((rdn_val_p != NULL) && (rdn_val_p->length == 0)) {
     433                ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!",
     434                                       ldb_dn_get_linearized(req->op.search.base));
     435                return LDB_ERR_INVALID_DN_SYNTAX;
     436        }
     437
     438        return ldb_next_request(module, req);
     439}
     440
     441static const struct ldb_module_ops ldb_rdn_name_module_ops = {
    331442        .name              = "rdn_name",
    332443        .add               = rdn_name_add,
     444        .modify            = rdn_name_modify,
    333445        .rename            = rdn_name_rename,
     446        .search            = rdn_name_search
    334447};
     448
     449int ldb_rdn_name_init(const char *version)
     450{
     451        LDB_MODULE_CHECK_VERSION(version);
     452        return ldb_register_module(&ldb_rdn_name_module_ops);
     453}
  • trunk/server/source4/lib/ldb/modules/skel.c

    r414 r745  
    1 /* 
     1/*
    22   ldb database library
    33
     
    77     ** library. This does NOT imply that all of Samba is released
    88     ** under the LGPL
    9    
     9
    1010   This library is free software; you can redistribute it and/or
    1111   modify it under the terms of the GNU Lesser General Public
     
    3232 */
    3333
     34#include "replace.h"
     35#include "system/filesys.h"
     36#include "system/time.h"
    3437#include "ldb_module.h"
    3538
     
    124127}
    125128
    126 const struct ldb_module_ops ldb_skel_module_ops = {
     129static const struct ldb_module_ops ldb_skel_module_ops = {
    127130        .name              = "skel",
    128131        .init_context      = skel_init,
     
    137140        .del_transaction   = skel_del_trans,
    138141};
     142
     143int ldb_skel_init(const char *version)
     144{
     145        LDB_MODULE_CHECK_VERSION(version);
     146        return ldb_register_module(&ldb_skel_module_ops);
     147}
  • trunk/server/source4/lib/ldb/modules/sort.c

    r414 r745  
    3232 */
    3333
     34#include "replace.h"
     35#include "system/filesys.h"
     36#include "system/time.h"
    3437#include "ldb_module.h"
    3538
     
    4548        struct ldb_module *module;
    4649
    47         char *attributeName;
    48         char *orderingRule;
     50        const char *attributeName;
     51        const char *orderingRule;
    4952        int reverse;
    5053
     
    5255        struct ldb_message **msgs;
    5356        char **referrals;
    54         int num_msgs;
    55         int num_refs;
     57        unsigned int num_msgs;
     58        unsigned int num_refs;
    5659
    5760        const struct ldb_schema_attribute *a;
     
    6366        struct ldb_control **controls;
    6467        struct ldb_sort_resp_control *resp;
    65         int i;
     68        unsigned int i;
    6669
    6770        if (*ctrls) {
     
    138141        struct ldb_context *ldb;
    139142        struct ldb_reply *ares;
    140         int i, ret;
     143        unsigned int i;
     144        int ret;
    141145
    142146        ldb = ldb_module_get_ctx(ac->module);
     
    145149        ac->sort_result = 0;
    146150
    147         ldb_qsort(ac->msgs, ac->num_msgs,
    148                   sizeof(struct ldb_message *),
    149                   ac, (ldb_qsort_cmp_fn_t)sort_compare);
     151        LDB_TYPESAFE_QSORT(ac->msgs, ac->num_msgs, ac, sort_compare);
    150152
    151153        if (ac->sort_result != LDB_SUCCESS) {
     
    316318                                        req);
    317319        if (ret != LDB_SUCCESS) {
    318                 return LDB_ERR_OPERATIONS_ERROR;
     320                return ret;
    319321        }
    320322
     
    322324        /* we do not need to replace them later as we
    323325         * are keeping the original req intact */
    324         if (!save_controls(control, down_req, &saved_controls)) {
     326        if (!ldb_save_controls(control, down_req, &saved_controls)) {
    325327                return LDB_ERR_OPERATIONS_ERROR;
    326328        }
     
    346348}
    347349
    348 const struct ldb_module_ops ldb_server_sort_module_ops = {
     350static const struct ldb_module_ops ldb_server_sort_module_ops = {
    349351        .name              = "server_sort",
    350352        .search            = server_sort_search,
    351353        .init_context      = server_sort_init
    352354};
     355
     356int ldb_server_sort_init(const char *version)
     357{
     358        LDB_MODULE_CHECK_VERSION(version);
     359        return ldb_register_module(&ldb_server_sort_module_ops);
     360}
  • trunk/server/source4/lib/ldb/nssldb/ldb-nss.c

    r414 r745  
    192192        size_t bufpos;
    193193        size_t lsize;
    194         int i;
     194        unsigned int i;
    195195
    196196        bufpos = 0;
     
    281281{
    282282        NSS_STATUS ret;
    283         int i;
     283        unsigned int i;
    284284
    285285        for (i = 0; i < grlist->count; i++) {
  • trunk/server/source4/lib/ldb/pyldb.c

    r414 r745  
    66   Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
    77   Copyright (C) 2006 Simo Sorce <idra@samba.org>
    8    Copyright (C) 2007-2009 Jelmer Vernooij <jelmer@samba.org>
    9    Copyright (C) 2009 Matthias Dieter Wallnöfer
    10 
    11         ** NOTE! The following LGPL license applies to the ldb
    12         ** library. This does NOT imply that all of Samba is released
    13         ** under the LGPL
     8   Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org>
     9   Copyright (C) 2009-2010 Matthias Dieter Wallnöfer
     10
     11    ** NOTE! The following LGPL license applies to the ldb
     12    ** library. This does NOT imply that all of Samba is released
     13    ** under the LGPL
    1414
    1515   This library is free software; you can redistribute it and/or
     
    2727*/
    2828
    29 #include "replace.h"
     29#include <Python.h>
     30#include <pytalloc.h>
    3031#include "ldb_private.h"
    31 #include <Python.h>
    3232#include "pyldb.h"
     33
     34void initldb(void);
     35static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
     36static PyObject *PyExc_LdbError;
     37
     38staticforward PyTypeObject PyLdbControl;
     39staticforward PyTypeObject PyLdbResult;
     40staticforward PyTypeObject PyLdbMessage;
     41staticforward PyTypeObject PyLdbModule;
     42staticforward PyTypeObject PyLdbDn;
     43staticforward PyTypeObject PyLdb;
     44staticforward PyTypeObject PyLdbMessageElement;
     45staticforward PyTypeObject PyLdbTree;
     46static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
     47static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
     48static struct ldb_message_element *PyObject_AsMessageElement(
     49                                                      TALLOC_CTX *mem_ctx,
     50                                                      PyObject *set_obj,
     51                                                      int flags,
     52                                                      const char *attr_name);
    3353
    3454/* There's no Py_ssize_t in 2.4, apparently */
     
    4363#endif
    4464
     65#define SIGN(a) (((a) == 0)?0:((a) < 0?-1:1))
     66
     67
     68
     69static PyObject *py_ldb_control_str(PyLdbControlObject *self)
     70{
     71        if (self->data != NULL) {
     72                char* control = ldb_control_to_string(self->mem_ctx, self->data);
     73                if (control == NULL) {
     74                        PyErr_NoMemory();
     75                        return NULL;
     76                }
     77                return PyString_FromString(control);
     78        } else {
     79                return PyString_FromFormat("ldb control");
     80        }
     81}
     82
     83static void py_ldb_control_dealloc(PyLdbControlObject *self)
     84{
     85        if (self->mem_ctx != NULL) {
     86                talloc_free(self->mem_ctx);
     87        }
     88        self->ob_type->tp_free(self);
     89}
     90
     91static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
     92{
     93        return PyString_FromString(self->data->oid);
     94}
     95
     96static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
     97{
     98        return PyBool_FromLong(self->data->critical);
     99}
     100
     101static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
     102{
     103        if (PyObject_IsTrue(value)) {
     104                self->data->critical = true;
     105        } else {
     106                self->data->critical = false;
     107        }
     108        return 0;
     109}
     110
     111static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     112{
     113        char *data = NULL;
     114        const char *array[2];
     115        const char * const kwnames[] = { "ldb", "data", NULL };
     116        struct ldb_control *parsed_controls;
     117        PyLdbControlObject *ret;
     118        PyObject *py_ldb;
     119        TALLOC_CTX *mem_ctx;
     120        struct ldb_context *ldb_ctx;
     121
     122        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
     123                                         discard_const_p(char *, kwnames),
     124                                         &py_ldb, &data))
     125                return NULL;
     126
     127        mem_ctx = talloc_new(NULL);
     128        if (mem_ctx == NULL) {
     129                PyErr_NoMemory();
     130                return NULL;
     131        }
     132
     133        ldb_ctx = PyLdb_AsLdbContext(py_ldb);
     134        parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
     135
     136        if (!parsed_controls) {
     137                talloc_free(mem_ctx);
     138                PyErr_SetString(PyExc_ValueError, "unable to parse control string");
     139                return NULL;
     140        }
     141
     142        ret = PyObject_New(PyLdbControlObject, type);
     143        if (ret == NULL) {
     144                PyErr_NoMemory();
     145                talloc_free(mem_ctx);
     146                return NULL;
     147        }
     148
     149        ret->mem_ctx = mem_ctx;
     150
     151        ret->data = talloc_steal(mem_ctx, parsed_controls);
     152        if (ret->data == NULL) {
     153                Py_DECREF(ret);
     154                PyErr_NoMemory();
     155                talloc_free(mem_ctx);
     156                return NULL;
     157        }
     158
     159        return (PyObject *)ret;
     160}
     161
     162static PyGetSetDef py_ldb_control_getset[] = {
     163        { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL },
     164        { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL },
     165        { NULL }
     166};
     167
     168static PyTypeObject PyLdbControl = {
     169        .tp_name = "ldb.control",
     170        .tp_dealloc = (destructor)py_ldb_control_dealloc,
     171        .tp_getattro = PyObject_GenericGetAttr,
     172        .tp_basicsize = sizeof(PyLdbControlObject),
     173        .tp_getset = py_ldb_control_getset,
     174        .tp_doc = "LDB control.",
     175        .tp_str = (reprfunc)py_ldb_control_str,
     176        .tp_new = py_ldb_control_new,
     177        .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
     178};
     179
    45180static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
    46181{
     
    49184
    50185        PyErr_SetObject(error,
    51                                         Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
    52                                   ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
    53 }
    54 
    55 static PyObject *PyExc_LdbError;
    56 
    57 PyAPI_DATA(PyTypeObject) PyLdbMessage;
    58 PyAPI_DATA(PyTypeObject) PyLdbModule;
    59 PyAPI_DATA(PyTypeObject) PyLdbDn;
    60 PyAPI_DATA(PyTypeObject) PyLdb;
    61 PyAPI_DATA(PyTypeObject) PyLdbMessageElement;
    62 PyAPI_DATA(PyTypeObject) PyLdbTree;
    63 
    64 static PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx,
    65                                                            struct ldb_message_element *el,
    66                                                            struct ldb_val *val)
    67 {
    68         struct ldb_val new_val;
    69         TALLOC_CTX *mem_ctx = talloc_new(NULL);
    70         PyObject *ret;
    71 
    72         new_val = *val;
    73 
    74         ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
    75 
    76         talloc_free(mem_ctx);
    77 
    78         return ret;
     186                        Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
     187                                      ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
     188}
     189
     190static PyObject *PyObject_FromLdbValue(struct ldb_val *val)
     191{
     192        return PyString_FromStringAndSize((const char *)val->data, val->length);
    79193}
    80194
    81195/**
    82  * Obtain a ldb DN from a Python object.
     196 * Create a Python object from a ldb_result.
    83197 *
    84  * @param mem_ctx Memory context
    85  * @param object Python object
    86  * @param ldb_ctx LDB context
    87  * @return Whether or not the conversion succeeded
     198 * @param result LDB result to convert
     199 * @return Python object with converted result (a list object)
    88200 */
    89 bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object,
    90                    struct ldb_context *ldb_ctx, struct ldb_dn **dn)
    91 {
    92         struct ldb_dn *odn;
    93 
    94         if (ldb_ctx != NULL && PyString_Check(object)) {
    95                 odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object));
    96                 *dn = odn;
    97                 return true;
    98         }
    99 
    100         if (PyLdbDn_Check(object)) {
    101                 *dn = PyLdbDn_AsDn(object);
    102                 return true;
    103         }
    104 
    105         PyErr_SetString(PyExc_TypeError, "Expected DN");
    106         return false;
     201static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
     202{
     203        TALLOC_CTX *ctl_ctx = talloc_new(NULL);
     204        PyLdbControlObject *ctrl;
     205        if (ctl_ctx == NULL) {
     206                PyErr_NoMemory();
     207                return NULL;
     208        }
     209
     210        ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
     211        if (ctrl == NULL) {
     212                PyErr_NoMemory();
     213                return NULL;
     214        }
     215        ctrl->mem_ctx = ctl_ctx;
     216        ctrl->data = talloc_steal(ctrl->mem_ctx, control);
     217        if (ctrl->data == NULL) {
     218                Py_DECREF(ctrl);
     219                PyErr_NoMemory();
     220                return NULL;
     221        }
     222        return (PyObject*) ctrl;
    107223}
    108224
     
    115231static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
    116232{
    117         PyObject *ret;
    118         int i;
     233        PyLdbResultObject *ret;
     234        PyObject *list, *controls, *referals;
     235        Py_ssize_t i;
     236
    119237        if (result == NULL) {
    120238                Py_RETURN_NONE;
    121         }
    122         ret = PyList_New(result->count);
     239        }
     240
     241        ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
     242        if (ret == NULL) {
     243                PyErr_NoMemory();
     244                return NULL;
     245        }
     246
     247        list = PyList_New(result->count);
     248        if (list == NULL) {
     249                PyErr_NoMemory();
     250                Py_DECREF(ret);
     251                return NULL;
     252        }
     253
    123254        for (i = 0; i < result->count; i++) {
    124                 PyList_SetItem(ret, i, PyLdbMessage_FromMessage(result->msgs[i])
    125                 );
    126         }
    127         return ret;
     255                PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
     256        }
     257
     258        ret->mem_ctx = talloc_new(NULL);
     259        if (ret->mem_ctx == NULL) {
     260                Py_DECREF(list);
     261                Py_DECREF(ret);
     262                PyErr_NoMemory();
     263                return NULL;
     264        }
     265
     266        ret->msgs = list;
     267
     268        if (result->controls) {
     269                controls = PyList_New(1);
     270                if (controls == NULL) {
     271                        Py_DECREF(ret);
     272                        PyErr_NoMemory();
     273                        return NULL;
     274                }
     275                for (i=0; result->controls[i]; i++) {
     276                        PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
     277                        if (ctrl == NULL) {
     278                                Py_DECREF(ret);
     279                                Py_DECREF(controls);
     280                                PyErr_NoMemory();
     281                                return NULL;
     282                        }
     283                        PyList_SetItem(controls, i, ctrl);
     284                }
     285        } else {
     286                /*
     287                 * No controls so we keep an empty list
     288                 */
     289                controls = PyList_New(0);
     290                if (controls == NULL) {
     291                        Py_DECREF(ret);
     292                        PyErr_NoMemory();
     293                        return NULL;
     294                }
     295        }
     296
     297        ret->controls = controls;
     298
     299        i = 0;
     300
     301        while (result->refs && result->refs[i]) {
     302                i++;
     303        }
     304
     305        referals = PyList_New(i);
     306        if (referals == NULL) {
     307                Py_DECREF(ret);
     308                PyErr_NoMemory();
     309                return NULL;
     310        }
     311
     312        for (i = 0;result->refs && result->refs[i]; i++) {
     313                PyList_SetItem(referals, i, PyString_FromString(result->refs[i]));
     314        }
     315        ret->referals = referals;
     316        return (PyObject *)ret;
    128317}
    129318
     
    137326 */
    138327static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
    139                                                                                            PyObject *obj)
     328                                               PyObject *obj)
    140329{
    141330        struct ldb_result *res;
    142         int i;
     331        Py_ssize_t i;
    143332
    144333        if (obj == Py_None)
     
    296485                "S.canonical_ex_str() -> string\n"
    297486                "Canonical version of this DN (like a posix path, with terminating newline)." },
    298         { "check_special", (PyCFunction)py_ldb_dn_is_special, METH_VARARGS,
    299                 NULL },
    300487        { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
    301488                "S.parent() -> dn\n"
     
    308495                "Add a base DN to this DN." },
    309496        { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
    310                 NULL },
     497                "S.check_special(name) -> bool\n\n"
     498                "Check if name is a special DN name"},
    311499        { NULL }
    312500};
     
    366554
    367555        ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
    368 
    369         if (ret == NULL || !ldb_dn_validate(ret)) {
     556        if (!ldb_dn_validate(ret)) {
    370557                talloc_free(mem_ctx);
    371558                PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
     
    384571}
    385572
    386 PyObject *PyLdbDn_FromDn(struct ldb_dn *dn)
    387 {
    388         PyLdbDnObject *py_ret;
    389 
    390         if (dn == NULL) {
    391                 Py_RETURN_NONE;
    392         }
    393 
    394         py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
    395         if (py_ret == NULL) {
    396                 PyErr_NoMemory();
    397                 return NULL;
    398         }
    399         py_ret->mem_ctx = talloc_new(NULL);
    400         py_ret->dn = talloc_reference(py_ret->mem_ctx, dn);
    401         return (PyObject *)py_ret;
    402 }
    403 
    404573static void py_ldb_dn_dealloc(PyLdbDnObject *self)
    405574{
    406575        talloc_free(self->mem_ctx);
    407         self->ob_type->tp_free(self);
    408 }
    409 
    410 PyTypeObject PyLdbDn = {
    411         .tp_name = "Dn",
     576        PyObject_Del(self);
     577}
     578
     579static PyTypeObject PyLdbDn = {
     580        .tp_name = "ldb.Dn",
    412581        .tp_methods = py_ldb_dn_methods,
    413582        .tp_str = (reprfunc)py_ldb_dn_get_linearized,
     
    418587        .tp_new = py_ldb_dn_new,
    419588        .tp_dealloc = (destructor)py_ldb_dn_dealloc,
    420         .tp_basicsize = sizeof(PyLdbObject),
     589        .tp_basicsize = sizeof(PyLdbDnObject),
    421590        .tp_flags = Py_TPFLAGS_DEFAULT,
    422591};
     
    475644{
    476645        PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
     646        Py_RETURN_NONE;
     647}
     648
     649static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self)
     650{
     651        PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_prepare_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
    477652        Py_RETURN_NONE;
    478653}
     
    529704
    530705static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
    531                                                                                 const char *paramname)
     706                                        const char *paramname)
    532707{
    533708        const char **ret;
    534         int i;
     709        Py_ssize_t i;
    535710        if (!PyList_Check(list)) {
    536711                PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
     
    538713        }
    539714        ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
     715        if (ret == NULL) {
     716                PyErr_NoMemory();
     717                return NULL;
     718        }
     719
    540720        for (i = 0; i < PyList_Size(list); i++) {
    541721                PyObject *item = PyList_GetItem(list, i);
     
    545725                }
    546726                ret[i] = talloc_strndup(ret, PyString_AsString(item),
    547                                                            PyString_Size(item));
     727                                        PyString_Size(item));
    548728        }
    549729        ret[i] = NULL;
     
    642822{
    643823        PyObject *py_msg;
    644         int ret;
    645         if (!PyArg_ParseTuple(args, "O", &py_msg))
    646                 return NULL;
    647 
    648         if (!PyLdbMessage_Check(py_msg)) {
    649                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
    650                 return NULL;
    651         }
    652 
    653         ret = ldb_modify(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg));
    654         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
    655 
    656         Py_RETURN_NONE;
    657 }
    658 
    659 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
    660 {
    661         PyObject *py_msg;
    662         int ret;
    663         Py_ssize_t dict_pos, msg_pos;
    664         struct ldb_message_element *msgel;
    665         struct ldb_message *msg;
     824        PyObject *py_controls = Py_None;
    666825        struct ldb_context *ldb_ctx;
    667826        struct ldb_request *req;
    668         PyObject *key, *value;
    669         PyObject *py_controls = Py_None;
     827        struct ldb_control **parsed_controls;
     828        struct ldb_message *msg;
     829        int ret;
    670830        TALLOC_CTX *mem_ctx;
    671         struct ldb_control **parsed_controls;
    672 
    673         if (!PyArg_ParseTuple(args, "O|O", &py_msg, &py_controls ))
    674                 return NULL;
     831
     832        if (!PyArg_ParseTuple(args, "O|O", &py_msg, &py_controls))
     833                return NULL;
     834
     835        mem_ctx = talloc_new(NULL);
     836        if (mem_ctx == NULL) {
     837                PyErr_NoMemory();
     838                return NULL;
     839        }
    675840        ldb_ctx = PyLdb_AsLdbContext(self);
    676841
    677         mem_ctx = talloc_new(NULL);
    678842        if (py_controls == Py_None) {
    679843                parsed_controls = NULL;
    680844        } else {
    681                 const char **controls = PyList_AsStringList(ldb_ctx, py_controls, "controls");
    682                 parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);
     845                const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
     846                parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
    683847                talloc_free(controls);
    684848        }
    685         if (PyDict_Check(py_msg)) {
    686                 PyObject *dn_value = PyDict_GetItemString(py_msg, "dn");
    687                 msg = ldb_msg_new(mem_ctx);
    688                 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg));
    689                 msg_pos = dict_pos = 0;
    690                 if (dn_value) {
    691                         if (!PyObject_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
    692                                 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
    693                                 talloc_free(mem_ctx);
    694                                 return NULL;
    695                         }
    696                         if (msg->dn == NULL) {
    697                                 PyErr_SetString(PyExc_TypeError, "dn set but not found");
    698                                 talloc_free(mem_ctx);
    699                                 return NULL;
    700                         }
    701                 }
    702 
    703                 while (PyDict_Next(py_msg, &dict_pos, &key, &value)) {
    704                         char *key_str = PyString_AsString(key);
    705                         if (strcmp(key_str, "dn") != 0) {
    706                                 msgel = PyObject_AsMessageElement(msg->elements, value, 0, key_str);
    707                                 if (msgel == NULL) {
    708                                         PyErr_SetString(PyExc_TypeError, "unable to import element");
    709                                         talloc_free(mem_ctx);
    710                                         return NULL;
    711                                 }
    712                                 memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel));
    713                                 msg_pos++;
    714                         }
    715                 }
    716 
    717                 if (msg->dn == NULL) {
    718                         PyErr_SetString(PyExc_TypeError, "no dn set");
    719                         talloc_free(mem_ctx);
    720                         return NULL;
    721                 }
    722 
    723                 msg->num_elements = msg_pos;
    724         } else {
    725                 msg = PyLdbMessage_AsMessage(py_msg);
    726         }
    727        
     849
     850        if (!PyLdbMessage_Check(py_msg)) {
     851                PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
     852                talloc_free(mem_ctx);
     853                return NULL;
     854        }
     855        msg = PyLdbMessage_AsMessage(py_msg);
     856
    728857        ret = ldb_msg_sanity_check(ldb_ctx, msg);
    729         if (ret != LDB_SUCCESS) {
    730                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
     858        if (ret != LDB_SUCCESS) {
     859                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    731860                talloc_free(mem_ctx);
    732861                return NULL;
    733         }
    734 
    735         ret = ldb_build_add_req(&req, ldb_ctx, ldb_ctx,
    736                                         msg,
    737                                         parsed_controls,
    738                                         NULL,
    739                                         ldb_op_default_callback,
    740                                         NULL);
    741 
     862        }
     863
     864        ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
     865                                NULL, ldb_op_default_callback, NULL);
    742866        if (ret != LDB_SUCCESS) {
    743867                PyErr_SetString(PyExc_TypeError, "failed to build request");
     
    746870        }
    747871
    748         /* do request and autostart a transaction */
     872        /* do request and autostart a transaction */
    749873        /* Then let's LDB handle the message error in case of pb as they are meaningful */
    750874
    751         ret = ldb_transaction_start(ldb_ctx);
    752         if (ret != LDB_SUCCESS) {
    753                 talloc_free(req);
     875        ret = ldb_transaction_start(ldb_ctx);
     876        if (ret != LDB_SUCCESS) {
    754877                talloc_free(mem_ctx);
    755                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
    756         }
    757 
    758         ret = ldb_request(ldb_ctx, req);
    759         if (ret == LDB_SUCCESS) {
    760                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    761         }
    762 
     878                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
     879        }
     880
     881        ret = ldb_request(ldb_ctx, req);
    763882        if (ret == LDB_SUCCESS) {
    764                 ret = ldb_transaction_commit(ldb_ctx);
    765         } else {
    766                 ldb_transaction_cancel(ldb_ctx);
     883                        ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     884        }
     885
     886        if (ret == LDB_SUCCESS) {
     887                ret = ldb_transaction_commit(ldb_ctx);
     888        } else {
     889                ldb_transaction_cancel(ldb_ctx);
    767890                if (ldb_ctx->err_string == NULL) {
    768891                        /* no error string was setup by the backend */
     
    770893                }
    771894        }
    772         talloc_free(req);
     895
    773896        talloc_free(mem_ctx);
    774         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
     897        PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
     898
     899        Py_RETURN_NONE;
     900}
     901
     902
     903/**
     904 * Obtain a ldb message from a Python Dictionary object.
     905 *
     906 * @param mem_ctx Memory context
     907 * @param py_obj Python Dictionary object
     908 * @param ldb_ctx LDB context
     909 * @param mod_flags Flags to be set on every message element
     910 * @return ldb_message on success or NULL on failure
     911 */
     912static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
     913                                            PyObject *py_obj,
     914                                            struct ldb_context *ldb_ctx,
     915                                            unsigned int mod_flags)
     916{
     917        struct ldb_message *msg;
     918        unsigned int msg_pos = 0;
     919        Py_ssize_t dict_pos = 0;
     920        PyObject *key, *value;
     921        struct ldb_message_element *msg_el;
     922        PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
     923
     924        msg = ldb_msg_new(mem_ctx);
     925        msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
     926
     927        if (dn_value) {
     928                if (!PyObject_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
     929                        PyErr_SetString(PyExc_TypeError, "unable to import dn object");
     930                        return NULL;
     931                }
     932                if (msg->dn == NULL) {
     933                        PyErr_SetString(PyExc_TypeError, "dn set but not found");
     934                        return NULL;
     935                }
     936        } else {
     937                PyErr_SetString(PyExc_TypeError, "no dn set");
     938                return NULL;
     939        }
     940
     941        while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
     942                char *key_str = PyString_AsString(key);
     943                if (strcmp(key_str, "dn") != 0) {
     944                        msg_el = PyObject_AsMessageElement(msg->elements, value,
     945                                                           mod_flags, key_str);
     946                        if (msg_el == NULL) {
     947                                PyErr_SetString(PyExc_TypeError, "unable to import element");
     948                                return NULL;
     949                        }
     950                        memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
     951                        msg_pos++;
     952                }
     953        }
     954
     955        msg->num_elements = msg_pos;
     956
     957        return msg;
     958}
     959
     960static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
     961{
     962        PyObject *py_obj;
     963        int ret;
     964        struct ldb_context *ldb_ctx;
     965        struct ldb_request *req;
     966        struct ldb_message *msg = NULL;
     967        PyObject *py_controls = Py_None;
     968        TALLOC_CTX *mem_ctx;
     969        struct ldb_control **parsed_controls;
     970
     971        if (!PyArg_ParseTuple(args, "O|O", &py_obj, &py_controls ))
     972                return NULL;
     973
     974        mem_ctx = talloc_new(NULL);
     975        if (mem_ctx == NULL) {
     976                PyErr_NoMemory();
     977                return NULL;
     978        }
     979        ldb_ctx = PyLdb_AsLdbContext(self);
     980
     981        if (py_controls == Py_None) {
     982                parsed_controls = NULL;
     983        } else {
     984                const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
     985                parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
     986                talloc_free(controls);
     987        }
     988
     989        if (PyLdbMessage_Check(py_obj)) {
     990                msg = PyLdbMessage_AsMessage(py_obj);
     991        } else if (PyDict_Check(py_obj)) {
     992                msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
     993        } else {
     994                PyErr_SetString(PyExc_TypeError,
     995                                "Dictionary or LdbMessage object expected!");
     996        }
     997
     998        if (!msg) {
     999                /* we should have a PyErr already set */
     1000                talloc_free(mem_ctx);
     1001                return NULL;
     1002        }
     1003
     1004        ret = ldb_msg_sanity_check(ldb_ctx, msg);
     1005        if (ret != LDB_SUCCESS) {
     1006                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
     1007                talloc_free(mem_ctx);
     1008                return NULL;
     1009        }
     1010
     1011        ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
     1012                                NULL, ldb_op_default_callback, NULL);
     1013        if (ret != LDB_SUCCESS) {
     1014                PyErr_SetString(PyExc_TypeError, "failed to build request");
     1015                talloc_free(mem_ctx);
     1016                return NULL;
     1017        }
     1018
     1019        /* do request and autostart a transaction */
     1020        /* Then let's LDB handle the message error in case of pb as they are meaningful */
     1021
     1022        ret = ldb_transaction_start(ldb_ctx);
     1023        if (ret != LDB_SUCCESS) {
     1024                talloc_free(mem_ctx);
     1025                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
     1026        }
     1027
     1028        ret = ldb_request(ldb_ctx, req);
     1029        if (ret == LDB_SUCCESS) {
     1030                        ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     1031        }
     1032
     1033        if (ret == LDB_SUCCESS) {
     1034                        ret = ldb_transaction_commit(ldb_ctx);
     1035        } else {
     1036                ldb_transaction_cancel(ldb_ctx);
     1037                if (ldb_ctx->err_string == NULL) {
     1038                        /* no error string was setup by the backend */
     1039                        ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
     1040                }
     1041        }
     1042
     1043        talloc_free(mem_ctx);
     1044        PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    7751045
    7761046        Py_RETURN_NONE;
     
    7821052        struct ldb_dn *dn;
    7831053        int ret;
    784         struct ldb_context *ldb;
    785         if (!PyArg_ParseTuple(args, "O", &py_dn))
    786                 return NULL;
    787 
    788         ldb = PyLdb_AsLdbContext(self);
    789 
    790         if (!PyObject_AsDn(NULL, py_dn, ldb, &dn))
    791                 return NULL;
    792 
    793         ret = ldb_delete(ldb, dn);
    794         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
     1054        struct ldb_context *ldb_ctx;
     1055        struct ldb_request *req;
     1056        PyObject *py_controls = Py_None;
     1057        TALLOC_CTX *mem_ctx;
     1058        struct ldb_control **parsed_controls;
     1059
     1060        if (!PyArg_ParseTuple(args, "O|O", &py_dn, &py_controls))
     1061                return NULL;
     1062
     1063        mem_ctx = talloc_new(NULL);
     1064        if (mem_ctx == NULL) {
     1065                PyErr_NoMemory();
     1066                return NULL;
     1067        }
     1068        ldb_ctx = PyLdb_AsLdbContext(self);
     1069
     1070        if (py_controls == Py_None) {
     1071                parsed_controls = NULL;
     1072        } else {
     1073                const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
     1074                parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
     1075                talloc_free(controls);
     1076        }
     1077
     1078        if (!PyObject_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
     1079                talloc_free(mem_ctx);
     1080                return NULL;
     1081        }
     1082
     1083        ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
     1084                                NULL, ldb_op_default_callback, NULL);
     1085        if (ret != LDB_SUCCESS) {
     1086                PyErr_SetString(PyExc_TypeError, "failed to build request");
     1087                talloc_free(mem_ctx);
     1088                return NULL;
     1089        }
     1090
     1091        /* do request and autostart a transaction */
     1092        /* Then let's LDB handle the message error in case of pb as they are meaningful */
     1093
     1094        ret = ldb_transaction_start(ldb_ctx);
     1095        if (ret != LDB_SUCCESS) {
     1096                talloc_free(mem_ctx);
     1097                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
     1098        }
     1099
     1100        ret = ldb_request(ldb_ctx, req);
     1101        if (ret == LDB_SUCCESS) {
     1102                ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     1103        }
     1104
     1105        if (ret == LDB_SUCCESS) {
     1106                ret = ldb_transaction_commit(ldb_ctx);
     1107        } else {
     1108                ldb_transaction_cancel(ldb_ctx);
     1109                if (ldb_ctx->err_string == NULL) {
     1110                        /* no error string was setup by the backend */
     1111                        ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
     1112                }
     1113        }
     1114
     1115        talloc_free(mem_ctx);
     1116        PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    7951117
    7961118        Py_RETURN_NONE;
     
    8041126        struct ldb_context *ldb;
    8051127        TALLOC_CTX *mem_ctx;
    806         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
    807                 return NULL;
     1128        PyObject *py_controls = Py_None;
     1129        struct ldb_control **parsed_controls;
     1130        struct ldb_context *ldb_ctx;
     1131        struct ldb_request *req;
     1132
     1133        ldb_ctx = PyLdb_AsLdbContext(self);
     1134
     1135        if (!PyArg_ParseTuple(args, "OO|O", &py_dn1, &py_dn2, &py_controls))
     1136                return NULL;
     1137
    8081138
    8091139        mem_ctx = talloc_new(NULL);
     
    8131143        }
    8141144        ldb = PyLdb_AsLdbContext(self);
     1145
     1146        if (py_controls == Py_None) {
     1147                parsed_controls = NULL;
     1148        } else {
     1149                const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
     1150                parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
     1151                talloc_free(controls);
     1152        }
     1153
     1154
    8151155        if (!PyObject_AsDn(mem_ctx, py_dn1, ldb, &dn1)) {
    8161156                talloc_free(mem_ctx);
     
    8231163        }
    8241164
    825         ret = ldb_rename(ldb, dn1, dn2);
     1165        ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
     1166                                NULL, ldb_op_default_callback, NULL);
     1167        if (ret != LDB_SUCCESS) {
     1168                PyErr_SetString(PyExc_TypeError, "failed to build request");
     1169                talloc_free(mem_ctx);
     1170                return NULL;
     1171        }
     1172
     1173        /* do request and autostart a transaction */
     1174        /* Then let's LDB handle the message error in case of pb as they are meaningful */
     1175
     1176        ret = ldb_transaction_start(ldb_ctx);
     1177        if (ret != LDB_SUCCESS) {
     1178                talloc_free(mem_ctx);
     1179                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
     1180        }
     1181
     1182        ret = ldb_request(ldb_ctx, req);
     1183        if (ret == LDB_SUCCESS) {
     1184                ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     1185        }
     1186
     1187        if (ret == LDB_SUCCESS) {
     1188                ret = ldb_transaction_commit(ldb_ctx);
     1189        } else {
     1190                ldb_transaction_cancel(ldb_ctx);
     1191                if (ldb_ctx->err_string == NULL) {
     1192                        /* no error string was setup by the backend */
     1193                        ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
     1194                }
     1195        }
     1196
    8261197        talloc_free(mem_ctx);
    827         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
     1198        PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    8281199
    8291200        Py_RETURN_NONE;
     
    8691240
    8701241
    871 static PyObject *py_ldb_write_ldif(PyLdbMessageObject *self, PyObject *args)
     1242static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
    8721243{
    8731244        int changetype;
     
    9381309static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
    9391310{
     1311        int ldb_ret;
    9401312        PyObject *py_msg_old;
    9411313        PyObject *py_msg_new;
    9421314        struct ldb_message *diff;
     1315        struct ldb_context *ldb;
    9431316        PyObject *py_ret;
    9441317
     
    9561329        }
    9571330
    958         diff = ldb_msg_diff(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg_old), PyLdbMessage_AsMessage(py_msg_new));
    959         if (diff == NULL)
    960                 return NULL;
     1331        ldb = PyLdb_AsLdbContext(self);
     1332        ldb_ret = ldb_msg_difference(ldb, ldb,
     1333                                     PyLdbMessage_AsMessage(py_msg_old),
     1334                                     PyLdbMessage_AsMessage(py_msg_new),
     1335                                     &diff);
     1336        if (ldb_ret != LDB_SUCCESS) {
     1337                PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
     1338                return NULL;
     1339        }
    9611340
    9621341        py_ret = PyLdbMessage_FromMessage(diff);
     1342
     1343        talloc_unlink(ldb, diff);
    9631344
    9641345        return py_ret;
     
    10041385{
    10051386        PyObject *py_base = Py_None;
    1006         enum ldb_scope scope = LDB_SCOPE_DEFAULT;
     1387        int scope = LDB_SCOPE_DEFAULT;
    10071388        char *expr = NULL;
    10081389        PyObject *py_attrs = Py_None;
     
    10171398        struct ldb_dn *base;
    10181399        PyObject *py_ret;
    1019 
     1400        TALLOC_CTX *mem_ctx;
     1401
     1402        /* type "int" rather than "enum" for "scope" is intentional */
    10201403        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
    10211404                                         discard_const_p(char *, kwnames),
     
    10231406                return NULL;
    10241407
     1408
     1409        mem_ctx = talloc_new(NULL);
     1410        if (mem_ctx == NULL) {
     1411                PyErr_NoMemory();
     1412                return NULL;
     1413        }
    10251414        ldb_ctx = PyLdb_AsLdbContext(self);
    10261415
     
    10281417                attrs = NULL;
    10291418        } else {
    1030                 attrs = PyList_AsStringList(NULL, py_attrs, "attrs");
    1031                 if (attrs == NULL)
     1419                attrs = PyList_AsStringList(mem_ctx, py_attrs, "attrs");
     1420                if (attrs == NULL) {
     1421                        talloc_free(mem_ctx);
    10321422                        return NULL;
     1423                }
    10331424        }
    10341425
     
    10451436                parsed_controls = NULL;
    10461437        } else {
    1047                 const char **controls = PyList_AsStringList(ldb_ctx, py_controls, "controls");
    1048                 parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);
     1438                const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
     1439                parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
    10491440                talloc_free(controls);
    10501441        }
    10511442
    1052         res = talloc_zero(ldb_ctx, struct ldb_result);
     1443        res = talloc_zero(mem_ctx, struct ldb_result);
    10531444        if (res == NULL) {
    10541445                PyErr_NoMemory();
    1055                 talloc_free(attrs);
    1056                 return NULL;
    1057         }
    1058 
    1059         ret = ldb_build_search_req(&req, ldb_ctx, ldb_ctx,
     1446                talloc_free(mem_ctx);
     1447                return NULL;
     1448        }
     1449
     1450        ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
    10601451                                   base,
    10611452                                   scope,
     
    10671458                                   NULL);
    10681459
     1460        if (ret != LDB_SUCCESS) {
     1461                talloc_free(mem_ctx);
     1462                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
     1463                return NULL;
     1464        }
     1465
    10691466        talloc_steal(req, attrs);
    1070 
    1071         if (ret != LDB_SUCCESS) {
    1072                 talloc_free(res);
    1073                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    1074                 return NULL;
    1075         }
    10761467
    10771468        ret = ldb_request(ldb_ctx, req);
     
    10811472        }
    10821473
    1083         talloc_free(req);
    1084 
    10851474        if (ret != LDB_SUCCESS) {
    1086                 talloc_free(res);
     1475                talloc_free(mem_ctx);
    10871476                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    10881477                return NULL;
     
    10911480        py_ret = PyLdbResult_FromResult(res);
    10921481
    1093         talloc_free(res);
     1482        talloc_free(mem_ctx);
    10941483
    10951484        return py_ret;
     
    11421531}
    11431532
     1533static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
     1534{
     1535        struct ldb_context *ldb = PyLdb_AsLdbContext(self);
     1536        int type, ret;
     1537        uint64_t value;
     1538
     1539        if (!PyArg_ParseTuple(args, "i", &type))
     1540                return NULL;
     1541
     1542        /* FIXME: More interpretation */
     1543
     1544        ret = ldb_sequence_number(ldb, type, &value);
     1545
     1546        if (ret != LDB_SUCCESS) {
     1547                PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
     1548                return NULL;
     1549        }
     1550        return PyLong_FromLongLong(value);
     1551}
    11441552static PyMethodDef py_ldb_methods[] = {
    11451553        { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
     
    11561564                "S.transaction_start() -> None\n"
    11571565                "Start a new transaction." },
     1566        { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
     1567                "S.transaction_prepare_commit() -> None\n"
     1568                "prepare to commit a new transaction (2-stage commit)." },
    11581569        { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
    11591570                "S.transaction_commit() -> None\n"
     
    12251636                "S.modules() -> list\n"
    12261637                "Return the list of modules on this LDB connection " },
     1638        { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
     1639                "S.sequence_number(type) -> value\n"
     1640                "Return the value of the sequence according to the requested type" },
    12271641        { NULL },
    12281642};
    12291643
    1230 PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
     1644static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
    12311645{
    12321646        PyLdbModuleObject *ret;
     
    12571671        struct ldb_dn *dn;
    12581672        struct ldb_result *result;
     1673        unsigned int count;
    12591674        int ret;
    1260         int count;
    1261 
    1262         if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn))
     1675
     1676        if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
    12631677                return -1;
    1264 
    1265         ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, NULL);
     1678        }
     1679
     1680        ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
     1681                         NULL);
    12661682        if (ret != LDB_SUCCESS) {
    12671683                PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
     
    12731689        talloc_free(result);
    12741690
     1691        if (count > 1) {
     1692                PyErr_Format(PyExc_RuntimeError,
     1693                             "Searching for [%s] dn gave %u results!",
     1694                             ldb_dn_get_linearized(dn),
     1695                             count);
     1696                return -1;
     1697        }
     1698
    12751699        return count;
    12761700}
     
    12801704};
    12811705
    1282 PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
     1706static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
    12831707{
    12841708        PyLdbObject *ret;
     
    13001724}
    13011725
    1302 PyTypeObject PyLdb = {
    1303         .tp_name = "Ldb",
     1726static PyTypeObject PyLdb = {
     1727        .tp_name = "ldb.Ldb",
    13041728        .tp_methods = py_ldb_methods,
    13051729        .tp_repr = (reprfunc)py_ldb_repr,
     
    13151739};
    13161740
     1741static void py_ldb_result_dealloc(PyLdbResultObject *self)
     1742{
     1743        talloc_free(self->mem_ctx);
     1744        Py_DECREF(self->msgs);
     1745        Py_DECREF(self->referals);
     1746        Py_DECREF(self->controls);
     1747        self->ob_type->tp_free(self);
     1748}
     1749
     1750static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
     1751{
     1752        Py_INCREF(self->msgs);
     1753        return self->msgs;
     1754}
     1755
     1756static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
     1757{
     1758        Py_INCREF(self->controls);
     1759        return self->controls;
     1760}
     1761
     1762static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
     1763{
     1764        Py_INCREF(self->referals);
     1765        return self->referals;
     1766}
     1767
     1768static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
     1769{
     1770        Py_ssize_t size;
     1771        if (self->msgs == NULL) {
     1772                PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
     1773                return NULL;
     1774        }
     1775        size = PyList_Size(self->msgs);
     1776        return PyInt_FromLong(size);
     1777}
     1778
     1779static PyGetSetDef py_ldb_result_getset[] = {
     1780        { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
     1781        { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
     1782        { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
     1783        { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
     1784        { NULL }
     1785};
     1786
     1787static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
     1788{
     1789        return PyObject_GetIter(self->msgs);
     1790}
     1791
     1792static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
     1793{
     1794        return PySequence_Size(self->msgs);
     1795}
     1796
     1797static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
     1798{
     1799        return PySequence_GetItem(self->msgs, idx);
     1800}
     1801
     1802static PySequenceMethods py_ldb_result_seq = {
     1803        .sq_length = (lenfunc)py_ldb_result_len,
     1804        .sq_item = (ssizeargfunc)py_ldb_result_find,
     1805};
     1806
     1807static PyObject *py_ldb_result_repr(PyLdbObject *self)
     1808{
     1809        return PyString_FromFormat("<ldb result>");
     1810}
     1811
     1812
     1813static PyTypeObject PyLdbResult = {
     1814        .tp_name = "ldb.Result",
     1815        .tp_repr = (reprfunc)py_ldb_result_repr,
     1816        .tp_dealloc = (destructor)py_ldb_result_dealloc,
     1817        .tp_iter = (getiterfunc)py_ldb_result_iter,
     1818        .tp_getset = py_ldb_result_getset,
     1819        .tp_getattro = PyObject_GenericGetAttr,
     1820        .tp_basicsize = sizeof(PyLdbResultObject),
     1821        .tp_as_sequence = &py_ldb_result_seq,
     1822        .tp_doc = "LDB result.",
     1823        .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
     1824};
     1825
    13171826static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
    13181827{
     
    13521861        const char * const*attrs;
    13531862
     1863        /* type "int" rather than "enum" for "scope" is intentional */
    13541864        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO",
    13551865                                         discard_const_p(char *, kwnames),
     
    14902000{
    14912001        talloc_free(self->mem_ctx);
    1492         self->ob_type->tp_free(self);
    1493 }
    1494 
    1495 PyTypeObject PyLdbModule = {
    1496         .tp_name = "LdbModule",
     2002        PyObject_Del(self);
     2003}
     2004
     2005static PyTypeObject PyLdbModule = {
     2006        .tp_name = "ldb.LdbModule",
    14972007        .tp_methods = py_ldb_module_methods,
    14982008        .tp_repr = (reprfunc)py_ldb_module_repr,
     
    15182028 * @return New ldb_message_element, allocated as child of mem_ctx
    15192029 */
    1520 struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
    1521                                                                                            PyObject *set_obj, int flags,
    1522                                                                                            const char *attr_name)
     2030static struct ldb_message_element *PyObject_AsMessageElement(
     2031                                                      TALLOC_CTX *mem_ctx,
     2032                                                      PyObject *set_obj,
     2033                                                      int flags,
     2034                                                      const char *attr_name)
    15232035{
    15242036        struct ldb_message_element *me;
    15252037
    1526         if (PyLdbMessageElement_Check(set_obj))
    1527                 return talloc_reference(mem_ctx,
    1528                                                                 PyLdbMessageElement_AsMessageElement(set_obj));
     2038        if (PyLdbMessageElement_Check(set_obj)) {
     2039                PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
     2040                /* We have to talloc_reference() the memory context, not the pointer
     2041                 * which may not actually be it's own context */
     2042                if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
     2043                        return PyLdbMessageElement_AsMessageElement(set_obj);
     2044                }
     2045                return NULL;
     2046        }
    15292047
    15302048        me = talloc(mem_ctx, struct ldb_message_element);
     2049        if (me == NULL) {
     2050                PyErr_NoMemory();
     2051                return NULL;
     2052        }
    15312053
    15322054        me->name = talloc_strdup(me, attr_name);
     
    15372059                me->values[0].length = PyString_Size(set_obj);
    15382060                me->values[0].data = talloc_memdup(me,
    1539                         (uint8_t *)PyString_AsString(set_obj), me->values[0].length);
     2061                        (uint8_t *)PyString_AsString(set_obj), me->values[0].length+1);
    15402062        } else if (PySequence_Check(set_obj)) {
    1541                 int i;
     2063                Py_ssize_t i;
    15422064                me->num_values = PySequence_Size(set_obj);
    15432065                me->values = talloc_array(me, struct ldb_val, me->num_values);
    15442066                for (i = 0; i < me->num_values; i++) {
    15452067                        PyObject *obj = PySequence_GetItem(set_obj, i);
     2068                        if (!PyString_Check(obj)) {
     2069                                PyErr_Format(PyExc_TypeError,
     2070                                             "Expected string as element %zd in list", i);
     2071                                talloc_free(me);
     2072                                return NULL;
     2073                        }
    15462074
    15472075                        me->values[i].length = PyString_Size(obj);
    15482076                        me->values[i].data = talloc_memdup(me,
    1549                                 (uint8_t *)PyString_AsString(obj), me->values[i].length);
     2077                                (uint8_t *)PyString_AsString(obj), me->values[i].length+1);
    15502078                }
    15512079        } else {
     
    15582086
    15592087
    1560 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, 
    1561                                                                  struct ldb_message_element *me)
    1562 {
    1563         int i;
     2088static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
     2089                                        struct ldb_message_element *me)
     2090{
     2091        Py_ssize_t i;
    15642092        PyObject *result;
    15652093
     
    15692097        for (i = 0; i < me->num_values; i++) {
    15702098                PyList_SetItem(result, i,
    1571                         PyObject_FromLdbValue(ldb_ctx, me, &me->values[i]));
     2099                        PyObject_FromLdbValue(&me->values[i]));
    15722100        }
    15732101
     
    15772105static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
    15782106{
    1579         int i;
    1580         if (!PyArg_ParseTuple(args, "i", &i))
    1581                 return NULL;
    1582         if (i < 0 || i >= PyLdbMessageElement_AsMessageElement(self)->num_values)
     2107        unsigned int i;
     2108        if (!PyArg_ParseTuple(args, "I", &i))
     2109                return NULL;
     2110        if (i >= PyLdbMessageElement_AsMessageElement(self)->num_values)
    15832111                Py_RETURN_NONE;
    15842112
    1585         return PyObject_FromLdbValue(NULL, PyLdbMessageElement_AsMessageElement(self),
    1586                                                                  &(PyLdbMessageElement_AsMessageElement(self)->values[i]));
     2113        return PyObject_FromLdbValue(&(PyLdbMessageElement_AsMessageElement(self)->values[i]));
    15872114}
    15882115
    15892116static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
    15902117{
    1591         struct ldb_message_element *el;
    1592 
    1593         el = PyLdbMessageElement_AsMessageElement(self);
     2118        struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
    15942119        return PyInt_FromLong(el->flags);
    15952120}
     
    16362161static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other)
    16372162{
    1638         return ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self),
    1639                                                                    PyLdbMessageElement_AsMessageElement(other));
     2163        int ret = ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self),
     2164                                                                          PyLdbMessageElement_AsMessageElement(other));
     2165        return SIGN(ret);
    16402166}
    16412167
     
    16452171}
    16462172
    1647 PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
     2173static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
    16482174{
    16492175        PyLdbMessageElementObject *ret;
    1650         ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);
     2176        ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
    16512177        if (ret == NULL) {
    16522178                PyErr_NoMemory();
     
    16842210
    16852211        el = talloc_zero(mem_ctx, struct ldb_message_element);
     2212        if (el == NULL) {
     2213                PyErr_NoMemory();
     2214                talloc_free(mem_ctx);
     2215                return NULL;
     2216        }
    16862217
    16872218        if (py_elements != NULL) {
    1688                 int i;
     2219                Py_ssize_t i;
    16892220                if (PyString_Check(py_elements)) {
    16902221                        el->num_values = 1;
    16912222                        el->values = talloc_array(el, struct ldb_val, 1);
     2223                        if (el->values == NULL) {
     2224                                talloc_free(mem_ctx);
     2225                                PyErr_NoMemory();
     2226                                return NULL;
     2227                        }
    16922228                        el->values[0].length = PyString_Size(py_elements);
    1693                         el->values[0].data = talloc_memdup(el,
    1694                                 (uint8_t *)PyString_AsString(py_elements), el->values[0].length);
     2229                        el->values[0].data = talloc_memdup(el->values,
     2230                                (uint8_t *)PyString_AsString(py_elements), el->values[0].length+1);
    16952231                } else if (PySequence_Check(py_elements)) {
    16962232                        el->num_values = PySequence_Size(py_elements);
    16972233                        el->values = talloc_array(el, struct ldb_val, el->num_values);
     2234                        if (el->values == NULL) {
     2235                                talloc_free(mem_ctx);
     2236                                PyErr_NoMemory();
     2237                                return NULL;
     2238                        }
    16982239                        for (i = 0; i < el->num_values; i++) {
    16992240                                PyObject *item = PySequence_GetItem(py_elements, i);
     2241                                if (item == NULL) {
     2242                                        talloc_free(mem_ctx);
     2243                                        return NULL;
     2244                                }
    17002245                                if (!PyString_Check(item)) {
    17012246                                        PyErr_Format(PyExc_TypeError,
    1702                                                         "Expected string as element %d in list",
    1703                                                         i);
     2247                                                     "Expected string as element %zd in list", i);
    17042248                                        talloc_free(mem_ctx);
    17052249                                        return NULL;
    17062250                                }
    17072251                                el->values[i].length = PyString_Size(item);
    1708                                 el->values[i].data = talloc_memdup(el, 
    1709                                         (uint8_t *)PyString_AsString(item), el->values[i].length);
     2252                                el->values[i].data = talloc_memdup(el,
     2253                                        (uint8_t *)PyString_AsString(item), el->values[i].length+1);
    17102254                        }
    17112255                } else {
     
    17202264        el->name = talloc_strdup(el, name);
    17212265
    1722         ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);
     2266        ret = PyObject_New(PyLdbMessageElementObject, type);
    17232267        if (ret == NULL) {
    1724                 PyErr_NoMemory();
    17252268                talloc_free(mem_ctx);
    17262269                return NULL;
     
    17352278{
    17362279        char *element_str = NULL;
    1737         int i;
     2280        Py_ssize_t i;
    17382281        struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
    17392282        PyObject *ret;
     
    17472290        }
    17482291
    1749         ret = PyString_FromFormat("MessageElement([%s])", element_str);
    1750 
    1751         talloc_free(element_str);
     2292        if (element_str != NULL) {
     2293                ret = PyString_FromFormat("MessageElement([%s])", element_str);
     2294                talloc_free(element_str);
     2295        } else {
     2296                ret = PyString_FromString("MessageElement([])");
     2297        }
    17522298
    17532299        return ret;
     
    17602306        if (el->num_values == 1)
    17612307                return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
    1762         else 
     2308        else
    17632309                Py_RETURN_NONE;
    17642310}
     
    17672313{
    17682314        talloc_free(self->mem_ctx);
    1769         self->ob_type->tp_free(self);
    1770 }
    1771 
    1772 PyTypeObject PyLdbMessageElement = {
    1773         .tp_name = "MessageElement",
     2315        PyObject_Del(self);
     2316}
     2317
     2318static PyTypeObject PyLdbMessageElement = {
     2319        .tp_name = "ldb.MessageElement",
    17742320        .tp_basicsize = sizeof(PyLdbMessageElementObject),
    17752321        .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
     
    17842330};
    17852331
     2332
     2333static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
     2334{
     2335        PyObject *py_ldb;
     2336        PyObject *py_dict;
     2337        PyObject *py_ret;
     2338        struct ldb_message *msg;
     2339        struct ldb_context *ldb_ctx;
     2340        unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
     2341
     2342        if (!PyArg_ParseTuple(args, "O!O!|I",
     2343                              &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
     2344                              &mod_flags)) {
     2345                return NULL;
     2346        }
     2347
     2348        /* mask only flags we are going to use */
     2349        mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
     2350        if (!mod_flags) {
     2351                PyErr_SetString(PyExc_ValueError,
     2352                                "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
     2353                                " expected as mod_flag value");
     2354                return NULL;
     2355        }
     2356
     2357        ldb_ctx = PyLdb_AsLdbContext(py_ldb);
     2358
     2359        msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
     2360        if (!msg) {
     2361                return NULL;
     2362        }
     2363
     2364        py_ret = PyLdbMessage_FromMessage(msg);
     2365
     2366        talloc_unlink(ldb_ctx, msg);
     2367
     2368        return py_ret;
     2369}
     2370
    17862371static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
    17872372{
     
    17982383{
    17992384        struct ldb_message *msg = PyLdbMessage_AsMessage(self);
    1800         int i, j = 0;
     2385        Py_ssize_t i, j = 0;
    18012386        PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
    18022387        if (msg->dn != NULL) {
     
    18272412                return NULL;
    18282413        }
    1829         return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg);
     2414        return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
    18302415}
    18312416
     
    18582443{
    18592444        struct ldb_message *msg = PyLdbMessage_AsMessage(self);
    1860         int i, j;
     2445        Py_ssize_t i, j = 0;
    18612446        PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
    1862         j = 0;
    18632447        if (msg->dn != NULL) {
    18642448                PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", PyLdbDn_FromDn(msg->dn)));
     
    18662450        }
    18672451        for (i = 0; i < msg->num_elements; i++, j++) {
    1868                 PyList_SetItem(l, j, Py_BuildValue("(sO)", msg->elements[i].name, PyLdbMessageElement_FromMessageElement(&msg->elements[i], self->msg)));
     2452                PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
     2453                PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
     2454                PyList_SetItem(l, j, value);
    18692455        }
    18702456        return l;
    18712457}
    18722458
    1873 static PyMethodDef py_ldb_msg_methods[] = {
    1874         { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, NULL },
    1875         { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, NULL },
     2459static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
     2460{
     2461        struct ldb_message *msg = PyLdbMessage_AsMessage(self);
     2462        Py_ssize_t i = 0;
     2463        PyObject *l = PyList_New(msg->num_elements);
     2464        for (i = 0; i < msg->num_elements; i++) {
     2465                PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
     2466        }
     2467        return l;
     2468}
     2469
     2470static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
     2471{
     2472        struct ldb_message *msg = PyLdbMessage_AsMessage(self);
     2473        PyLdbMessageElementObject *py_element;
     2474        int ret;
     2475        struct ldb_message_element *el;
     2476
     2477        if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
     2478                return NULL;
     2479
     2480        el = talloc_reference(msg, py_element->el);
     2481        if (el == NULL) {
     2482                PyErr_NoMemory();
     2483                return NULL;
     2484        }
     2485
     2486        ret = ldb_msg_add(msg, el, el->flags);
     2487        PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
     2488
     2489        Py_RETURN_NONE;
     2490}
     2491
     2492static PyMethodDef py_ldb_msg_methods[] = {
     2493        { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
     2494                "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
     2495                "Class method to create ldb.Message object from Dictionary.\n"
     2496                "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
     2497        { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
     2498                "S.keys() -> list\n\n"
     2499                "Return sequence of all attribute names." },
     2500        { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
     2501                "S.remove(name)\n\n"
     2502                "Remove all entries for attributes with the specified name."},
    18762503        { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS, NULL },
    18772504        { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
     2505        { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
     2506        { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
     2507                "S.append(element)\n\n"
     2508                "Add an element to this message." },
    18782509        { NULL },
    18792510};
     
    18972528                return -1;
    18982529        }
    1899        
     2530
    19002531        attr_name = PyString_AsString(name);
    19012532        if (value == NULL) {
     
    19042535        } else {
    19052536                struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
    1906                                                                                         value, 0, attr_name);
     2537                                                                           value, 0, attr_name);
    19072538                if (el == NULL)
    19082539                        return -1;
     
    19712602}
    19722603
    1973 PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
     2604static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
    19742605{
    19752606        PyLdbMessageObject *ret;
     
    20212652{
    20222653        talloc_free(self->mem_ctx);
    2023         self->ob_type->tp_free(self);
    2024 }
    2025 
    2026 PyTypeObject PyLdbMessage = {
    2027         .tp_name = "Message",
     2654        PyObject_Del(self);
     2655}
     2656
     2657static int py_ldb_msg_compare(PyLdbMessageObject *py_msg1,
     2658                              PyLdbMessageObject *py_msg2)
     2659{
     2660        struct ldb_message *msg1 = PyLdbMessage_AsMessage(py_msg1),
     2661                           *msg2 = PyLdbMessage_AsMessage(py_msg2);
     2662        unsigned int i;
     2663        int ret;
     2664
     2665        if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
     2666                ret = ldb_dn_compare(msg1->dn, msg2->dn);
     2667                if (ret != 0) {
     2668                        return SIGN(ret);
     2669                }
     2670        }
     2671
     2672        ret = msg1->num_elements - msg2->num_elements;
     2673        if (ret != 0) {
     2674                return SIGN(ret);
     2675        }
     2676
     2677        for (i = 0; i < msg1->num_elements; i++) {
     2678                ret = ldb_msg_element_compare_name(&msg1->elements[i],
     2679                                                   &msg2->elements[i]);
     2680                if (ret != 0) {
     2681                        return SIGN(ret);
     2682                }
     2683
     2684                ret = ldb_msg_element_compare(&msg1->elements[i],
     2685                                              &msg2->elements[i]);
     2686                if (ret != 0) {
     2687                        return SIGN(ret);
     2688                }
     2689        }
     2690
     2691        return 0;
     2692}
     2693
     2694static PyTypeObject PyLdbMessage = {
     2695        .tp_name = "ldb.Message",
    20282696        .tp_methods = py_ldb_msg_methods,
    20292697        .tp_getset = py_ldb_msg_getset,
     
    20352703        .tp_flags = Py_TPFLAGS_DEFAULT,
    20362704        .tp_iter = (getiterfunc)py_ldb_msg_iter,
     2705        .tp_compare = (cmpfunc)py_ldb_msg_compare,
    20372706};
    20382707
    2039 PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
     2708static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
    20402709{
    20412710        PyLdbTreeObject *ret;
     
    20552724{
    20562725        talloc_free(self->mem_ctx);
    2057         self->ob_type->tp_free(self);
    2058 }
    2059 
    2060 PyTypeObject PyLdbTree = {
    2061         .tp_name = "Tree",
     2726        PyObject_Del(self);
     2727}
     2728
     2729static PyTypeObject PyLdbTree = {
     2730        .tp_name = "ldb.Tree",
    20622731        .tp_basicsize = sizeof(PyLdbTreeObject),
    20632732        .tp_dealloc = (destructor)py_ldb_tree_dealloc,
     
    23673036static PyObject *py_timestring(PyObject *module, PyObject *args)
    23683037{
    2369         time_t t;
     3038        /* most times "time_t" is a signed integer type with 32 or 64 bit:
     3039         * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
     3040        long int t_val;
    23703041        char *tresult;
    23713042        PyObject *ret;
    2372         if (!PyArg_ParseTuple(args, "L", &t))
    2373                 return NULL;
    2374         tresult = ldb_timestring(NULL, t);
     3043        if (!PyArg_ParseTuple(args, "l", &t_val))
     3044                return NULL;
     3045        tresult = ldb_timestring(NULL, (time_t) t_val);
    23753046        ret = PyString_FromString(tresult);
    23763047        talloc_free(tresult);
     
    24353106                return;
    24363107
     3108        if (PyType_Ready(&PyLdbResult) < 0)
     3109                return;
     3110
     3111        if (PyType_Ready(&PyLdbControl) < 0)
     3112                return;
     3113
    24373114        m = Py_InitModule3("ldb", py_ldb_global_methods,
    24383115                "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server.");
     
    24403117                return;
    24413118
     3119        PyModule_AddObject(m, "SEQ_HIGHEST_SEQ", PyInt_FromLong(LDB_SEQ_HIGHEST_SEQ));
     3120        PyModule_AddObject(m, "SEQ_HIGHEST_TIMESTAMP", PyInt_FromLong(LDB_SEQ_HIGHEST_TIMESTAMP));
     3121        PyModule_AddObject(m, "SEQ_NEXT", PyInt_FromLong(LDB_SEQ_NEXT));
    24423122        PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT));
    24433123        PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE));
     
    24943174        PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER));
    24953175
    2496         PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY));
    2497         PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC));
    2498         PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT));
    2499         PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP));
    2500 
     3176        PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY));
     3177        PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC));
     3178        PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT));
     3179        PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP));
    25013180
    25023181        PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
     
    25113190        Py_INCREF(&PyLdbMessageElement);
    25123191        Py_INCREF(&PyLdbTree);
     3192        Py_INCREF(&PyLdbResult);
     3193        Py_INCREF(&PyLdbControl);
    25133194
    25143195        PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
     
    25183199        PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
    25193200        PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
    2520 }
     3201        PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
     3202
     3203        PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
     3204}
  • trunk/server/source4/lib/ldb/pyldb.h

    r414 r745  
    22   Unix SMB/CIFS implementation.
    33
    4    Swig interface to ldb.
     4   Python interface to ldb.
    55
    66   Copyright (C) 2007-2008 Jelmer Vernooij <jelmer@samba.org>
     
    2727#define _PYLDB_H_
    2828
    29 #include <Python.h>
    3029#include <talloc.h>
    3130
    3231typedef struct {
    3332        PyObject_HEAD
     33        TALLOC_CTX *mem_ctx;
    3434        struct ldb_context *ldb_ctx;
    35         TALLOC_CTX *mem_ctx;
    3635} PyLdbObject;
    3736
    38 PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
    3937#define PyLdb_AsLdbContext(pyobj) ((PyLdbObject *)pyobj)->ldb_ctx
    4038#define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
     
    4240typedef struct {
    4341        PyObject_HEAD
     42        TALLOC_CTX *mem_ctx;
    4443        struct ldb_dn *dn;
    45         TALLOC_CTX *mem_ctx;
    4644} PyLdbDnObject;
    4745
     
    5351typedef struct {
    5452        PyObject_HEAD
     53        TALLOC_CTX *mem_ctx;
    5554        struct ldb_message *msg;
    56         TALLOC_CTX *mem_ctx;
    5755} PyLdbMessageObject;
    5856#define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
     
    6159typedef struct {
    6260        PyObject_HEAD
     61        TALLOC_CTX *mem_ctx;
    6362        struct ldb_module *mod;
    64         TALLOC_CTX *mem_ctx;
    6563} PyLdbModuleObject;
    66 PyObject *PyLdbMessage_FromMessage(struct ldb_message *message);
    67 PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
    6864#define PyLdbModule_AsModule(pyobj) ((PyLdbModuleObject *)pyobj)->mod
    6965
    7066typedef struct {
    71         PyObject_HEAD   
     67        PyObject_HEAD
     68        TALLOC_CTX *mem_ctx;
    7269        struct ldb_message_element *el;
    73         TALLOC_CTX *mem_ctx;
    7470} PyLdbMessageElementObject;
    75 struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx, PyObject *obj, int flags, const char *name);
    76 PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *, TALLOC_CTX *mem_ctx);
    7771#define PyLdbMessageElement_AsMessageElement(pyobj) ((PyLdbMessageElementObject *)pyobj)->el
    7872#define PyLdbMessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
     
    8074typedef struct {
    8175        PyObject_HEAD
     76        TALLOC_CTX *mem_ctx;
    8277        struct ldb_parse_tree *tree;
     78} PyLdbTreeObject;
     79#define PyLdbTree_AsTree(pyobj) ((PyLdbTreeObject *)pyobj)->tree
     80
     81typedef struct {
     82        PyObject_HEAD
    8383        TALLOC_CTX *mem_ctx;
    84 } PyLdbTreeObject;
    85 PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *);
    86 #define PyLdbTree_AsTree(pyobj) ((PyLdbTreeObject *)pyobj)->tree
     84        PyObject *msgs;
     85        PyObject *referals;
     86        PyObject *controls;
     87} PyLdbResultObject;
     88
     89typedef struct {
     90        PyObject_HEAD
     91        TALLOC_CTX *mem_ctx;
     92        struct ldb_control *data;
     93} PyLdbControlObject;
    8794
    8895#define PyErr_LDB_ERROR_IS_ERR_RAISE(err,ret,ldb) \
  • trunk/server/source4/lib/ldb/tests/photo.ldif

    r414 r745  
    22changetype: modify
    33add: jpegPhoto
    4 jpegPhoto:< file://tests/tmp/samba4.png
     4jpegPhoto:< file://tests/samba4.png
    55
  • trunk/server/source4/lib/ldb/tests/python/api.py

    r414 r745  
    1 #!/usr/bin/python
     1#!/usr/bin/env python
    22# Simple tests for the ldb python bindings.
    33# Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
    44
    5 import os, sys
     5import os
    66import unittest
    77
    8 # Required for the standalone LDB build
    9 sys.path.append("build/lib.linux-i686-2.4")
    10 
    118import ldb
    129
     10
    1311def filename():
    14     return os.tempnam()
     12    import tempfile
     13    try:
     14        dir_prefix = os.path.join(os.environ["SELFTEST_PREFIX"], "tmp")
     15    except KeyError:
     16        dir_prefix = None
     17    return tempfile.mktemp(dir=dir_prefix)
    1518
    1619class NoContextTests(unittest.TestCase):
     
    5861
    5962    def test_modules_tdb(self):
    60         x = ldb.Ldb("bar.ldb")
     63        x = ldb.Ldb(filename())
    6164        self.assertEquals("[<ldb module 'tdb'>]", repr(x.modules()))
    6265
     
    7881
    7982    def test_search_attr_string(self):
    80         l = ldb.Ldb("foo.tdb")
     83        l = ldb.Ldb(filename())
    8184        self.assertRaises(TypeError, l.search, attrs="dc")
    8285
     
    9699        self.assertRaises(ldb.LdbError, lambda: l.delete(ldb.Dn(l, "dc=foo2")))
    97100
     101    def test_delete_w_unhandled_ctrl(self):
     102        l = ldb.Ldb(filename())
     103        m = ldb.Message()
     104        m.dn = ldb.Dn(l, "dc=foo1")
     105        m["b"] = ["a"]
     106        l.add(m)
     107        self.assertRaises(ldb.LdbError, lambda: l.delete(m.dn, ["search_options:1:2"]))
     108        l.delete(m.dn)
     109
    98110    def test_contains(self):
    99         l = ldb.Ldb(filename())
     111        name = filename()
     112        l = ldb.Ldb(name)
    100113        self.assertFalse(ldb.Dn(l, "dc=foo3") in l)
    101         l = ldb.Ldb(filename())
     114        l = ldb.Ldb(name)
    102115        m = ldb.Message()
    103116        m.dn = ldb.Dn(l, "dc=foo3")
     
    209222            rm = l.search(m.dn)[0]
    210223            self.assertEquals(1, len(rm))
    211             rm = l.search(m.dn, attrs=["bla"])[0]
     224            rm = l.search(m.dn, attrs=["bla"])
    212225            self.assertEquals(0, len(rm))
    213226        finally:
     
    267280            self.assertEquals(2, len(rm))
    268281            self.assertEquals(["1234", "456"], list(rm["bla"]))
    269            
    270             #Now create another modify, but switch the flags before we do it
     282
     283            # Now create another modify, but switch the flags before we do it
    271284            m["bla"] = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla")
    272285            m["bla"].set_flags(ldb.FLAG_MOD_DELETE)
     
    275288            self.assertEquals(1, len(rm))
    276289            self.assertEquals(["1234"], list(rm["bla"]))
    277            
    278290        finally:
    279291            l.delete(ldb.Dn(l, "dc=add"))
     
    316328        self.assertEquals("foo\0bar", res[0]["displayname"][0])
    317329
     330    def test_no_crash_broken_expr(self):
     331        l = ldb.Ldb(filename())
     332        self.assertRaises(ldb.LdbError,lambda: l.search("", ldb.SCOPE_SUBTREE, "&(dc=*)(dn=*)", ["dc"]))
     333
    318334
    319335class DnTests(unittest.TestCase):
     
    332348        y = ldb.Dn(self.ldb, "dc=foo11,bar=bloe")
    333349        self.assertEquals(x, y)
     350        y = ldb.Dn(self.ldb, "dc=foo11,bar=blie")
     351        self.assertNotEquals(x, y)
    334352
    335353    def test_str(self):
     
    356374        x = ldb.Dn(self.ldb, "@BLA")
    357375        self.assertEquals(None, x.parent())
    358 
    359     def test_compare(self):
    360         x = ldb.Dn(self.ldb, "dc=foo17,bar=bloe")
    361         y = ldb.Dn(self.ldb, "dc=foo17,bar=bloe")
    362         self.assertEquals(x, y)
    363         z = ldb.Dn(self.ldb, "dc=foo17,bar=blie")
    364         self.assertNotEquals(z, y)
    365376
    366377    def test_is_valid(self):
     
    368379        self.assertTrue(x.is_valid())
    369380        x = ldb.Dn(self.ldb, "")
    370         # is_valid()'s return values appears to be a side effect of
    371         # some other ldb functions. yuck.
    372         # self.assertFalse(x.is_valid())
     381        self.assertTrue(x.is_valid())
    373382
    374383    def test_is_special(self):
     
    413422        ldif = self.ldb.write_ldif(msg[1], ldb.CHANGETYPE_NONE)
    414423        self.assertEquals("dn: foo=bar\n\n", ldif)
    415        
     424
    416425    def test_parse_ldif_more(self):
    417426        msgs = self.ldb.parse_ldif("dn: foo=bar\n\n\ndn: bar=bar")
     
    441450    def test_iter_items(self):
    442451        self.assertEquals(0, len(self.msg.items()))
    443         self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "dc=foo28")
     452        self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "dc=foo28")
    444453        self.assertEquals(1, len(self.msg.items()))
    445454
    446455    def test_repr(self):
    447         self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "dc=foo29")
     456        self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "dc=foo29")
    448457        self.msg["dc"] = "foo"
    449458        self.assertEquals("Message({'dn': Dn('dc=foo29'), 'dc': MessageElement(['foo'])})", repr(self.msg))
     
    457466    def test_del(self):
    458467        del self.msg["foo"]
     468
     469    def test_add(self):
     470        self.msg.add(ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla"))
     471
     472    def test_elements_empty(self):
     473        self.assertEquals([], self.msg.elements())
     474
     475    def test_elements(self):
     476        el = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla")
     477        self.msg.add(el)
     478        self.assertEquals([el], self.msg.elements())
    459479
    460480    def test_add_value(self):
     
    476496
    477497    def test_keys(self):
    478         self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "@BASEINFO")
     498        self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "@BASEINFO")
    479499        self.msg["foo"] = ["bla"]
    480500        self.msg["bar"] = ["bla"]
     
    486506
    487507    def test_get_dn(self):
    488         self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "@BASEINFO")
     508        self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "@BASEINFO")
    489509        self.assertEquals("@BASEINFO", self.msg.get("dn").__str__())
    490510
    491511    def test_get_invalid(self):
    492         self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "@BASEINFO")
     512        self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "@BASEINFO")
    493513        self.assertRaises(TypeError, self.msg.get, 42)
    494514
     
    510530        self.assertEquals(1, len(msgdiff))
    511531
     532    def test_equal_empty(self):
     533        msg1 = ldb.Message()
     534        msg2 = ldb.Message()
     535        self.assertEquals(msg1, msg2)
     536
     537    def test_equal_simplel(self):
     538        db = ldb.Ldb(filename())
     539        msg1 = ldb.Message()
     540        msg1.dn = ldb.Dn(db, "foo=bar")
     541        msg2 = ldb.Message()
     542        msg2.dn = ldb.Dn(db, "foo=bar")
     543        self.assertEquals(msg1, msg2)
     544        msg1['foo'] = 'bar'
     545        msg2['foo'] = 'bar'
     546        self.assertEquals(msg1, msg2)
     547        msg2['foo'] = 'blie'
     548        self.assertNotEquals(msg1, msg2)
     549        msg2['foo'] = 'blie'
     550
     551    def test_from_dict(self):
     552        rec = {"dn": "dc=fromdict",
     553               "a1": ["a1-val1", "a1-val1"]}
     554        l = ldb.Ldb()
     555        # check different types of input Flags
     556        for flags in [ldb.FLAG_MOD_ADD, ldb.FLAG_MOD_REPLACE, ldb.FLAG_MOD_DELETE]:
     557            m = ldb.Message.from_dict(l, rec, flags)
     558            self.assertEquals(rec["a1"], list(m["a1"]))
     559            self.assertEquals(flags, m["a1"].flags())
     560        # check input params
     561        self.assertRaises(TypeError, ldb.Message.from_dict, dict(), rec, ldb.FLAG_MOD_REPLACE)
     562        self.assertRaises(TypeError, ldb.Message.from_dict, l, list(), ldb.FLAG_MOD_REPLACE)
     563        self.assertRaises(ValueError, ldb.Message.from_dict, l, rec, 0)
     564        # Message.from_dict expects dictionary with 'dn'
     565        err_rec = {"a1": ["a1-val1", "a1-val1"]}
     566        self.assertRaises(TypeError, ldb.Message.from_dict, l, err_rec, ldb.FLAG_MOD_REPLACE)
     567
    512568
    513569
     
    552608        self.assertEquals(y, x)
    553609
     610    def test_extended(self):
     611        el = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla")
     612        self.assertEquals("MessageElement(['456'])", repr(el))
     613
    554614
    555615class ModuleTests(unittest.TestCase):
     
    572632                return self.next.search(*args, **kwargs)
    573633
     634        def request(self, *args, **kwargs):
     635            pass
     636
     637        name = filename()
    574638        ldb.register_module(ExampleModule)
    575         if os.path.exists("usemodule.ldb"):
    576             os.unlink("usemodule.ldb")
    577         l = ldb.Ldb("usemodule.ldb")
     639        if os.path.exists(name):
     640            os.unlink(name)
     641        l = ldb.Ldb(name)
    578642        l.add({"dn": "@MODULES", "@LIST": "bla"})
    579643        self.assertEquals([], ops)
    580         l = ldb.Ldb("usemodule.ldb")
     644        l = ldb.Ldb(name)
    581645        self.assertEquals(["init"], ops)
     646
     647class LdbResultTests(unittest.TestCase):
     648
     649    def setUp(self):
     650        name = filename()
     651        self.name = name
     652        if os.path.exists(name):
     653            os.unlink(name)
     654        self.l = ldb.Ldb(name)
     655        self.l.add({"dn": "DC=SAMBA,DC=ORG", "name": "samba.org"})
     656        self.l.add({"dn": "OU=ADMIN,DC=SAMBA,DC=ORG", "name": "Admins"})
     657        self.l.add({"dn": "OU=USERS,DC=SAMBA,DC=ORG", "name": "Users"})
     658        self.l.add({"dn": "OU=OU1,DC=SAMBA,DC=ORG", "name": "OU #1"})
     659        self.l.add({"dn": "OU=OU2,DC=SAMBA,DC=ORG", "name": "OU #2"})
     660        self.l.add({"dn": "OU=OU3,DC=SAMBA,DC=ORG", "name": "OU #3"})
     661        self.l.add({"dn": "OU=OU4,DC=SAMBA,DC=ORG", "name": "OU #4"})
     662        self.l.add({"dn": "OU=OU5,DC=SAMBA,DC=ORG", "name": "OU #5"})
     663        self.l.add({"dn": "OU=OU6,DC=SAMBA,DC=ORG", "name": "OU #6"})
     664        self.l.add({"dn": "OU=OU7,DC=SAMBA,DC=ORG", "name": "OU #7"})
     665        self.l.add({"dn": "OU=OU8,DC=SAMBA,DC=ORG", "name": "OU #8"})
     666        self.l.add({"dn": "OU=OU9,DC=SAMBA,DC=ORG", "name": "OU #9"})
     667        self.l.add({"dn": "OU=OU10,DC=SAMBA,DC=ORG", "name": "OU #10"})
     668
     669    def tearDown(self):
     670        if os.path.exists(self.name):
     671            os.unlink(self.name)
     672
     673    def test_return_type(self):
     674        res = self.l.search()
     675        self.assertEquals(str(res), "<ldb result>")
     676
     677    def test_get_msgs(self):
     678        res = self.l.search()
     679        list = res.msgs
     680
     681    def test_get_controls(self):
     682        res = self.l.search()
     683        list = res.controls
     684
     685    def test_get_referals(self):
     686        res = self.l.search()
     687        list = res.referals
     688
     689    def test_iter_msgs(self):
     690        found = False
     691        for l in self.l.search().msgs:
     692            if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG":
     693                found = True
     694        self.assertTrue(found)
     695
     696    def test_iter_msgs_count(self):
     697        self.assertTrue(self.l.search().count > 0)
     698        # 13 objects has been added to the DC=SAMBA, DC=ORG
     699        self.assertEqual(self.l.search(base="DC=SAMBA,DC=ORG").count, 13)
     700
     701    def test_iter_controls(self):
     702        res = self.l.search().controls
     703        it = iter(res)
     704
     705    def test_create_control(self):
     706        self.assertRaises(ValueError, ldb.Control, self.l, "tatayoyo:0")
     707        c = ldb.Control(self.l, "relax:1")
     708        self.assertEquals(c.critical, True)
     709        self.assertEquals(c.oid, "1.3.6.1.4.1.4203.666.5.12")
     710
     711    def test_iter_refs(self):
     712        res = self.l.search().referals
     713        it = iter(res)
     714
     715    def test_iter_as_sequence_msgs(self):
     716        found = False
     717        res = self.l.search().msgs
     718
     719        for i in range(0, len(res)):
     720            l = res[i]
     721            if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG":
     722                found = True
     723        self.assertTrue(found)
     724
     725    def test_iter_as_sequence(self):
     726        found = False
     727        res = self.l.search()
     728
     729        for i in range(0, len(res)):
     730            l = res[i]
     731            if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG":
     732                found = True
     733        self.assertTrue(found)
     734
     735class VersionTests(unittest.TestCase):
     736
     737    def test_version(self):
     738        self.assertTrue(isinstance(ldb.__version__, str))
    582739
    583740
  • trunk/server/source4/lib/ldb/tests/sample_module.c

    r414 r745  
    2222*/
    2323
     24#include "replace.h"
     25#include "system/filesys.h"
     26#include "system/time.h"
    2427#include "ldb_module.h"
    2528
    26 int sample_add(struct ldb_module *mod, struct ldb_request *req)
     29static int sample_add(struct ldb_module *mod, struct ldb_request *req)
    2730{
     31        struct ldb_control *control;
     32
    2833        ldb_msg_add_fmt(req->op.add.message, "touchedBy", "sample");
    2934
    30         return ldb_next_request(mod, req);
     35        /* check if there's a relax control */
     36        control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
     37        if (control == NULL) {
     38                /* not found go on */
     39                return ldb_next_request(mod, req);
     40        } else {
     41                return LDB_ERR_UNWILLING_TO_PERFORM;
     42        }
    3143}
    3244
    33 const struct ldb_module_ops ldb_sample_module_ops = {
     45static int sample_modify(struct ldb_module *mod, struct ldb_request *req)
     46{
     47        struct ldb_control *control;
     48
     49        /* check if there's a relax control */
     50        control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
     51        if (control == NULL) {
     52                /* not found go on */
     53                return ldb_next_request(mod, req);
     54        } else {
     55                return LDB_ERR_UNWILLING_TO_PERFORM;
     56        }
     57}
     58
     59
     60static struct ldb_module_ops ldb_sample_module_ops = {
    3461        .name              = "sample",
    3562        .add               = sample_add,
     63        .del               = sample_modify,
     64        .modify            = sample_modify,
    3665};
     66
     67int ldb_sample_init(const char *version)
     68{
     69        LDB_MODULE_CHECK_VERSION(version);
     70        return ldb_register_module(&ldb_sample_module_ops);
     71}
  • trunk/server/source4/lib/ldb/tests/test-generic.sh

    r414 r745  
    4545}
    4646
    47 echo "testing indexed search"
     47echo "Testing indexed search"
    4848$VALGRIND ldbsearch$EXEEXT '(uid=uham)'  || exit 1
    4949$VALGRIND ldbsearch$EXEEXT '(&(objectclass=person)(objectclass=person)(objectclass=top))' || exit 1
     
    8282
    8383echo "Testing binary file attribute value"
    84 mkdir -p tests/tmp
    85 cp $LDBDIR/tests/samba4.png tests/tmp/samba4.png
    8684$VALGRIND ldbmodify$EXEEXT $LDBDIR/tests/photo.ldif || exit 1
    8785count=`$VALGRIND ldbsearch$EXEEXT '(cn=Hampster Ursula)' jpegPhoto | grep '^dn' | wc -l`
     
    9088    exit 1
    9189fi
    92 rm -f tests/tmp/samba4.png
    9390
    9491echo "*TODO* Testing UTF8 upper lower case searches !!"
  • trunk/server/source4/lib/ldb/tests/test-schema.sh

    r414 r745  
    2020$VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-3.ldif || exit 1
    2121$VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-4.ldif
    22 if [ "$?" == "0" ]; then
     22if [ "$?" = "0" ]; then
    2323        echo "test failed!"
    2424        exit 1
    2525fi
    2626$VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-5.ldif
    27 if [ "$?" == "0" ]; then
     27if [ "$?" = "0" ]; then
    2828        echo "test failed!"
    2929        exit 1
  • trunk/server/source4/lib/ldb/tests/test-tdb.sh

    r414 r745  
    3030
    3131. $LDBDIR/tests/test-tdb-features.sh
     32
     33. $LDBDIR/tests/test-controls.sh
  • trunk/server/source4/lib/ldb/tests/test.ldif

    r414 r745  
    410410facsimiletelephonenumber: +1 313 555 9700
    411411telephonenumber: +1 313 555 5331
     412
     413dn: cn=Fred Bassett,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST
     414objectclass: OpenLDAPperson
     415cn: Fred Bassett
     416sn: Bassett
     417uid: Bassett, Fred
  • trunk/server/source4/lib/ldb/tools/cmdline.c

    r414 r745  
    2222*/
    2323
    24 #include "ldb_includes.h"
     24#include "replace.h"
     25#include "system/filesys.h"
     26#include "system/time.h"
    2527#include "ldb.h"
     28#include "ldb_module.h"
    2629#include "tools/cmdline.h"
    2730
    28 #if (_SAMBA_BUILD_ >= 4)
    29 #include "includes.h"
    30 #include "lib/cmdline/popt_common.h"
    31 #include "lib/ldb-samba/ldif_handlers.h"
    32 #include "auth/gensec/gensec.h"
    33 #include "auth/auth.h"
    34 #include "ldb_wrap.h"
    35 #include "param/param.h"
    36 #endif
    37 
    3831static struct ldb_cmdline options; /* needs to be static for older compilers */
    3932
    40 static struct poptOption popt_options[] = {
     33enum ldb_cmdline_options { CMDLINE_RELAX=1 };
     34
     35static struct poptOption builtin_popt_options[] = {
    4136        POPT_AUTOHELP
    4237        { "url",       'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" },
     
    5449        { "nosync", 0,   POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL },
    5550        { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL },
    56         { "input", 'I', POPT_ARG_STRING, &options.input, 0, "Input File", "Input" },
    57         { "output", 'O', POPT_ARG_STRING, &options.output, 0, "Output File", "Output" },
    5851        { NULL,    'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" },
    5952        { "controls", 0, POPT_ARG_STRING, NULL, 'c', "controls", NULL },
    6053        { "show-binary", 0, POPT_ARG_NONE, &options.show_binary, 0, "display binary LDIF", NULL },
    61 #if (_SAMBA_BUILD_ >= 4)
    62         POPT_COMMON_SAMBA
    63         POPT_COMMON_CREDENTIALS
    64         POPT_COMMON_CONNECTION
    65         POPT_COMMON_VERSION
    66 #endif
     54        { "paged", 0, POPT_ARG_NONE, NULL, 'P', "use a paged search", NULL },
     55        { "show-deleted", 0, POPT_ARG_NONE, NULL, 'D', "show deleted objects", NULL },
     56        { "show-recycled", 0, POPT_ARG_NONE, NULL, 'R', "show recycled objects", NULL },
     57        { "show-deactivated-link", 0, POPT_ARG_NONE, NULL, 'd', "show deactivated links", NULL },
     58        { "reveal", 0, POPT_ARG_NONE, NULL, 'r', "reveal ldb internals", NULL },
     59        { "relax", 0, POPT_ARG_NONE, NULL, CMDLINE_RELAX, "pass relax control", NULL },
     60        { "cross-ncs", 0, POPT_ARG_NONE, NULL, 'N', "search across NC boundaries", NULL },
     61        { "extended-dn", 0, POPT_ARG_NONE, NULL, 'E', "show extended DNs", NULL },
    6762        { NULL }
    6863};
    6964
    70 void ldb_cmdline_help(const char *cmdname, FILE *f)
     65void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f)
    7166{
    7267        poptContext pc;
    73         pc = poptGetContext(cmdname, 0, NULL, popt_options,
     68        struct poptOption **popt_options = ldb_module_popt_options(ldb);
     69        pc = poptGetContext(cmdname, 0, NULL, *popt_options,
    7470                            POPT_CONTEXT_KEEP_FIRST);
    7571        poptPrintHelp(pc, f, 0);
     72}
     73
     74/*
     75  add a control to the options structure
     76 */
     77static bool add_control(TALLOC_CTX *mem_ctx, const char *control)
     78{
     79        unsigned int i;
     80
     81        /* count how many controls we already have */
     82        for (i=0; options.controls && options.controls[i]; i++) ;
     83
     84        options.controls = talloc_realloc(mem_ctx, options.controls, const char *, i + 2);
     85        if (options.controls == NULL) {
     86                return false;
     87        }
     88        options.controls[i] = control;
     89        options.controls[i+1] = NULL;
     90        return true;
    7691}
    7792
     
    8196struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb,
    8297                                        int argc, const char **argv,
    83                                         void (*usage)(void))
     98                                        void (*usage)(struct ldb_context *))
    8499{
    85100        struct ldb_cmdline *ret=NULL;
    86101        poptContext pc;
    87 #if (_SAMBA_BUILD_ >= 4)
    88         int r;
    89 #endif
    90102        int num_options = 0;
    91103        int opt;
    92104        int flags = 0;
    93 
    94 #if (_SAMBA_BUILD_ >= 4)
    95         r = ldb_register_samba_handlers(ldb);
    96         if (r != 0) {
    97                 goto failed;
    98         }
    99 
    100 #endif
     105        int rc;
     106        struct poptOption **popt_options;
     107
     108        /* make the ldb utilities line buffered */
     109        setlinebuf(stdout);
    101110
    102111        ret = talloc_zero(ldb, struct ldb_cmdline);
     
    122131        options.scope = LDB_SCOPE_DEFAULT;
    123132
    124         pc = poptGetContext(argv[0], argc, argv, popt_options,
     133        popt_options = ldb_module_popt_options(ldb);
     134        (*popt_options) = builtin_popt_options;
     135
     136        rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_OPTIONS);
     137        if (rc != LDB_SUCCESS) {
     138                fprintf(stderr, "ldb: failed to run command line hooks : %s\n", ldb_strerror(rc));
     139                goto failed;
     140        }
     141
     142        pc = poptGetContext(argv[0], argc, argv, *popt_options,
    125143                            POPT_CONTEXT_KEEP_FIRST);
    126144
     
    160178                case 'c': {
    161179                        const char *cs = poptGetOptArg(pc);
    162                         const char *p, *q;
    163                         int cc;
    164 
    165                         for (p = cs, cc = 1; (q = strchr(p, ',')); cc++, p = q + 1) ;
    166 
    167                         options.controls = talloc_array(ret, char *, cc + 1);
    168                         if (options.controls == NULL) {
    169                                 fprintf(stderr, "Out of memory!\n");
    170                                 goto failed;
    171                         }
    172                         for (p = cs, cc = 0; p != NULL; cc++) {
    173                                 const char *t;
     180                        const char *p;
     181
     182                        for (p = cs; p != NULL; ) {
     183                                const char *t, *c;
    174184
    175185                                t = strchr(p, ',');
    176186                                if (t == NULL) {
    177                                         options.controls[cc] = talloc_strdup(options.controls, p);
     187                                        c = talloc_strdup(options.controls, p);
    178188                                        p = NULL;
    179189                                } else {
    180                                         options.controls[cc] = talloc_strndup(options.controls, p, t-p);
     190                                        c = talloc_strndup(options.controls, p, t-p);
    181191                                        p = t + 1;
    182192                                }
    183                         }
    184                         options.controls[cc] = NULL;
     193                                if (c == NULL || !add_control(ret, c)) {
     194                                        fprintf(stderr, __location__ ": out of memory\n");
     195                                        goto failed;
     196                                }
     197                        }
    185198
    186199                        break;   
    187200                }
     201                case 'P':
     202                        if (!add_control(ret, "paged_results:1:1024")) {
     203                                fprintf(stderr, __location__ ": out of memory\n");
     204                                goto failed;
     205                        }
     206                        break;
     207                case 'D':
     208                        if (!add_control(ret, "show_deleted:1")) {
     209                                fprintf(stderr, __location__ ": out of memory\n");
     210                                goto failed;
     211                        }
     212                        break;
     213                case 'R':
     214                        if (!add_control(ret, "show_recycled:0")) {
     215                                fprintf(stderr, __location__ ": out of memory\n");
     216                                goto failed;
     217                        }
     218                        break;
     219                case 'd':
     220                        if (!add_control(ret, "show_deactivated_link:0")) {
     221                                fprintf(stderr, __location__ ": out of memory\n");
     222                                goto failed;
     223                        }
     224                        break;
     225                case 'r':
     226                        if (!add_control(ret, "reveal_internals:0")) {
     227                                fprintf(stderr, __location__ ": out of memory\n");
     228                                goto failed;
     229                        }
     230                        break;
     231                case CMDLINE_RELAX:
     232                        if (!add_control(ret, "relax:0")) {
     233                                fprintf(stderr, __location__ ": out of memory\n");
     234                                goto failed;
     235                        }
     236                        break;
     237                case 'N':
     238                        if (!add_control(ret, "search_options:1:2")) {
     239                                fprintf(stderr, __location__ ": out of memory\n");
     240                                goto failed;
     241                        }
     242                        break;
     243                case 'E':
     244                        if (!add_control(ret, "extended_dn:1:1")) {
     245                                fprintf(stderr, __location__ ": out of memory\n");
     246                                goto failed;
     247                        }
     248                        break;
    188249                default:
    189250                        fprintf(stderr, "Invalid option %s: %s\n",
    190251                                poptBadOption(pc, 0), poptStrerror(opt));
    191                         if (usage) usage();
     252                        if (usage) usage(ldb);
    192253                        goto failed;
    193254                }
     
    206267        if (ret->url == NULL) {
    207268                fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n");
    208                 if (usage) usage();
     269                if (usage) usage(ldb);
    209270                goto failed;
    210271        }
     
    226287        }
    227288
    228 #if (_SAMBA_BUILD_ >= 4)
    229         /* Must be after we have processed command line options */
    230         gensec_init(cmdline_lp_ctx);
    231        
    232         if (ldb_set_opaque(ldb, "sessionInfo", system_session(ldb, cmdline_lp_ctx))) {
    233                 goto failed;
    234         }
    235         if (ldb_set_opaque(ldb, "credentials", cmdline_credentials)) {
    236                 goto failed;
    237         }
    238         if (ldb_set_opaque(ldb, "loadparm", cmdline_lp_ctx)) {
    239                 goto failed;
    240         }
    241 
    242         ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
    243 #endif
    244 
    245289        if (options.modules_path != NULL) {
    246290                ldb_set_modules_dir(ldb, options.modules_path);
    247         } else if (getenv("LDB_MODULES_PATH") != NULL) {
    248                 ldb_set_modules_dir(ldb, getenv("LDB_MODULES_PATH"));
     291        }
     292
     293        rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_PRECONNECT);
     294        if (rc != LDB_SUCCESS) {
     295                fprintf(stderr, "ldb: failed to run preconnect hooks : %s\n", ldb_strerror(rc));
     296                goto failed;
    249297        }
    250298
     
    256304        }
    257305
     306        rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_POSTCONNECT);
     307        if (rc != LDB_SUCCESS) {
     308                fprintf(stderr, "ldb: failed to run post connect hooks : %s\n", ldb_strerror(rc));
     309                goto failed;
     310        }
     311
    258312        return ret;
    259313
    260314failed:
    261315        talloc_free(ret);
    262         exit(1);
     316        exit(LDB_ERR_OPERATIONS_ERROR);
    263317        return NULL;
    264318}
     
    274328int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request)
    275329{
    276         int i, j;
    277         int ret = 0;
     330        unsigned int i, j;
     331        int ret = 0;
    278332
    279333        if (reply == NULL || request == NULL) return -1;
  • trunk/server/source4/lib/ldb/tools/cmdline.h

    r414 r745  
    4242        int num_searches;
    4343        const char *sasl_mechanism;
    44         const char *input;
    45         const char *output;
    46         char **controls;
     44        const char **controls;
    4745        int show_binary;
    4846        int tracing;
    4947};
    5048
    51 struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv,
    52                                         void (*usage)(void));
     49struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc,
     50                                        const char **argv,
     51                                        void (*usage)(struct ldb_context *));
    5352
    5453
    5554int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request);
    56 void ldb_cmdline_help(const char *cmdname, FILE *f);
     55void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f);
    5756
  • trunk/server/source4/lib/ldb/tools/ldbadd.c

    r414 r745  
    1 /* 
     1/*
    22   ldb database library
    33
     
    77     ** library. This does NOT imply that all of Samba is released
    88     ** under the LGPL
    9    
     9
    1010   This library is free software; you can redistribute it and/or
    1111   modify it under the terms of the GNU Lesser General Public
     
    3434#include "ldb.h"
    3535#include "tools/cmdline.h"
     36#include "ldbutil.h"
    3637
    37 static int failures;
     38static unsigned int failures;
     39static struct ldb_cmdline *options;
    3840
    39 static void usage(void)
     41static void usage(struct ldb_context *ldb)
    4042{
    41         printf("Usage: ldbadd <options> <ldif...>\n"); 
     43        printf("Usage: ldbadd <options> <ldif...>\n");
    4244        printf("Adds records to a ldb, reading ldif the specified list of files\n\n");
    43         ldb_cmdline_help("ldbadd", stdout);
    44         exit(1);
     45        ldb_cmdline_help(ldb, "ldbadd", stdout);
     46        exit(LDB_ERR_OPERATIONS_ERROR);
    4547}
    4648
     
    4951  add records from an opened file
    5052*/
    51 static int process_file(struct ldb_context *ldb, FILE *f, int *count)
     53static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
    5254{
    5355        struct ldb_ldif *ldif;
    5456        int ret = LDB_SUCCESS;
     57        struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
     58        if (options->controls != NULL &&  req_ctrls== NULL) {
     59                printf("parsing controls failed: %s\n", ldb_errstring(ldb));
     60                return LDB_ERR_OPERATIONS_ERROR;
     61        }
     62
    5563
    5664        while ((ldif = ldb_ldif_read_file(ldb, f))) {
     
    6169                }
    6270
    63                 ldif->msg = ldb_msg_canonicalize(ldb, ldif->msg);
     71                ret = ldb_msg_normalize(ldb, ldif, ldif->msg, &ldif->msg);
     72                if (ret != LDB_SUCCESS) {
     73                        fprintf(stderr,
     74                                "ERR: Message canonicalize failed - %s\n",
     75                                ldb_strerror(ret));
     76                        failures++;
     77                        ldb_ldif_read_free(ldb, ldif);
     78                        continue;
     79                }
    6480
    65                 ret = ldb_add(ldb, ldif->msg);
     81                ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls);
    6682                if (ret != LDB_SUCCESS) {
    67                         fprintf(stderr, "ERR: \"%s\" on DN %s\n",
    68                                 ldb_errstring(ldb), ldb_dn_get_linearized(ldif->msg->dn));
     83                        fprintf(stderr, "ERR: %s : \"%s\" on DN %s\n",
     84                                ldb_strerror(ret), ldb_errstring(ldb),
     85                                ldb_dn_get_linearized(ldif->msg->dn));
    6986                        failures++;
    7087                } else {
    7188                        (*count)++;
     89                        if (options->verbose) {
     90                                printf("Added %s\n", ldb_dn_get_linearized(ldif->msg->dn));
     91                        }
    7292                }
    7393                ldb_ldif_read_free(ldb, ldif);
     
    82102{
    83103        struct ldb_context *ldb;
    84         int i, ret=0, count=0;
    85         struct ldb_cmdline *options;
     104        unsigned int i, count = 0;
     105        int ret = LDB_SUCCESS;
     106        TALLOC_CTX *mem_ctx = talloc_new(NULL);
    86107
    87         ldb = ldb_init(NULL, NULL);
     108        ldb = ldb_init(mem_ctx, NULL);
     109        if (ldb == NULL) {
     110                return LDB_ERR_OPERATIONS_ERROR;
     111        }
    88112
    89113        options = ldb_cmdline_process(ldb, argc, argv, usage);
    90114
    91         if (ldb_transaction_start(ldb) != 0) {
     115        ret = ldb_transaction_start(ldb);
     116        if (ret != LDB_SUCCESS) {
    92117                printf("Failed to start transaction: %s\n", ldb_errstring(ldb));
    93                 exit(1);
     118                return ret;
    94119        }
    95120
     
    103128                        if (!f) {
    104129                                perror(fname);
    105                                 exit(1);
     130                                return LDB_ERR_OPERATIONS_ERROR;
    106131                        }
    107132                        ret = process_file(ldb, f, &count);
     
    111136
    112137        if (count != 0) {
    113                 if (ldb_transaction_commit(ldb) != 0) {
     138                ret = ldb_transaction_commit(ldb);
     139                if (ret != LDB_SUCCESS) {
    114140                        printf("Failed to commit transaction: %s\n", ldb_errstring(ldb));
    115                         exit(1);
     141                        return ret;
    116142                }
    117143        } else {
     
    119145        }
    120146
    121         talloc_free(ldb);
     147        talloc_free(mem_ctx);
    122148
    123         printf("Added %d records with %d failures\n", count, failures);
    124        
     149        printf("Added %u records with %u failures\n", count, failures);
     150
    125151        return ret;
    126152}
  • trunk/server/source4/lib/ldb/tools/ldbdel.c

    r414 r745  
    3232 */
    3333
     34#include "replace.h"
    3435#include "ldb.h"
    3536#include "tools/cmdline.h"
     37#include "ldbutil.h"
    3638
    37 static int ldb_delete_recursive(struct ldb_context *ldb, struct ldb_dn *dn)
     39static int dn_cmp(struct ldb_message **msg1, struct ldb_message **msg2)
    3840{
    39         int ret, i, total=0;
     41        return ldb_dn_compare((*msg1)->dn, (*msg2)->dn);
     42}
     43
     44static int ldb_delete_recursive(struct ldb_context *ldb, struct ldb_dn *dn,struct ldb_control **req_ctrls)
     45{
     46        int ret;
     47        unsigned int i, total=0;
    4048        const char *attrs[] = { NULL };
    4149        struct ldb_result *res;
    4250       
    4351        ret = ldb_search(ldb, ldb, &res, dn, LDB_SCOPE_SUBTREE, attrs, "distinguishedName=*");
    44         if (ret != LDB_SUCCESS) return -1;
     52        if (ret != LDB_SUCCESS) return ret;
     53
     54        /* sort the DNs, deepest first */
     55        TYPESAFE_QSORT(res->msgs, res->count, dn_cmp);
    4556
    4657        for (i = 0; i < res->count; i++) {
    47                 if (ldb_delete(ldb, res->msgs[i]->dn) == 0) {
     58                if (ldb_delete_ctrl(ldb, res->msgs[i]->dn,req_ctrls) == LDB_SUCCESS) {
    4859                        total++;
     60                } else {
     61                        printf("Failed to delete '%s' - %s\n",
     62                               ldb_dn_get_linearized(res->msgs[i]->dn),
     63                               ldb_errstring(ldb));
    4964                }
    5065        }
     
    5368
    5469        if (total == 0) {
    55                 return -1;
     70                return LDB_ERR_OPERATIONS_ERROR;
    5671        }
    57         printf("Deleted %d records\n", total);
    58         return 0;
     72        printf("Deleted %u records\n", total);
     73        return LDB_SUCCESS;
    5974}
    6075
    61 static void usage(void)
     76static void usage(struct ldb_context *ldb)
    6277{
    6378        printf("Usage: ldbdel <options> <DN...>\n");
    6479        printf("Deletes records from a ldb\n\n");
    65         ldb_cmdline_help("ldbdel", stdout);
    66         exit(1);
     80        ldb_cmdline_help(ldb, "ldbdel", stdout);
     81        exit(LDB_ERR_OPERATIONS_ERROR);
    6782}
    6883
    6984int main(int argc, const char **argv)
    7085{
     86        struct ldb_control **req_ctrls;
     87        struct ldb_cmdline *options;
    7188        struct ldb_context *ldb;
    7289        int ret = 0, i;
    73         struct ldb_cmdline *options;
     90        TALLOC_CTX *mem_ctx = talloc_new(NULL);
    7491
    75         ldb = ldb_init(NULL, NULL);
     92        ldb = ldb_init(mem_ctx, NULL);
     93        if (ldb == NULL) {
     94                return LDB_ERR_OPERATIONS_ERROR;
     95        }
    7696
    7797        options = ldb_cmdline_process(ldb, argc, argv, usage);
    7898
    7999        if (options->argc < 1) {
    80                 usage();
    81                 exit(1);
     100                usage(ldb);
     101        }
     102
     103        req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
     104        if (options->controls != NULL &&  req_ctrls== NULL) {
     105                printf("parsing controls failed: %s\n", ldb_errstring(ldb));
     106                return LDB_ERR_OPERATIONS_ERROR;
    82107        }
    83108
     
    86111
    87112                dn = ldb_dn_new(ldb, ldb, options->argv[i]);
    88                 if ( ! ldb_dn_validate(dn)) {
    89                         printf("Invalid DN format\n");
    90                         exit(1);
     113                if (dn == NULL) {
     114                        return LDB_ERR_OPERATIONS_ERROR;
    91115                }
    92116                if (options->recursive) {
    93                         ret = ldb_delete_recursive(ldb, dn);
     117                        ret = ldb_delete_recursive(ldb, dn,req_ctrls);
    94118                } else {
    95                         ret = ldb_delete(ldb, dn);
    96                         if (ret == 0) {
     119                        ret = ldb_delete_ctrl(ldb, dn,req_ctrls);
     120                        if (ret == LDB_SUCCESS) {
    97121                                printf("Deleted 1 record\n");
    98122                        }
    99123                }
    100                 if (ret != 0) {
    101                         printf("delete of '%s' failed - %s\n",
    102                                 ldb_dn_get_linearized(dn),
    103                                 ldb_errstring(ldb));
     124                if (ret != LDB_SUCCESS) {
     125                        printf("delete of '%s' failed - (%s) %s\n",
     126                               ldb_dn_get_linearized(dn),
     127                               ldb_strerror(ret),
     128                               ldb_errstring(ldb));
    104129                }
    105130        }
    106131
    107         talloc_free(ldb);
     132        talloc_free(mem_ctx);
    108133
    109134        return ret;
  • trunk/server/source4/lib/ldb/tools/ldbedit.c

    r414 r745  
    1 /* 
     1/*
    22   ldb database library
    33
     
    77     ** library. This does NOT imply that all of Samba is released
    88     ** under the LGPL
    9    
     9
    1010   This library is free software; you can redistribute it and/or
    1111   modify it under the terms of the GNU Lesser General Public
     
    3131 *  Author: Andrew Tridgell
    3232 */
    33 #include "ldb_includes.h"
     33
     34#include "replace.h"
     35#include "system/filesys.h"
     36#include "system/time.h"
     37#include "system/filesys.h"
    3438#include "ldb.h"
    3539#include "tools/cmdline.h"
     40#include "tools/ldbutil.h"
    3641
    3742static struct ldb_cmdline *options;
    3843
    3944/*
    40   debug routine 
    41 */
    42 static void ldif_write_msg(struct ldb_context *ldb, 
    43                            FILE *f, 
     45  debug routine
     46*/
     47static void ldif_write_msg(struct ldb_context *ldb,
     48                           FILE *f,
    4449                           enum ldb_changetype changetype,
    4550                           struct ldb_message *msg)
     
    5560  returns the number of modified elements
    5661*/
    57 static int modify_record(struct ldb_context *ldb, 
     62static int modify_record(struct ldb_context *ldb,
    5863                         struct ldb_message *msg1,
    59                          struct ldb_message *msg2)
    60 {
     64                         struct ldb_message *msg2,
     65                         struct ldb_control **req_ctrls)
     66{
     67        int ret;
    6168        struct ldb_message *mod;
    6269
    63         mod = ldb_msg_diff(ldb, msg1, msg2);
    64         if (mod == NULL) {
     70        if (ldb_msg_difference(ldb, ldb, msg1, msg2, &mod) != LDB_SUCCESS) {
    6571                fprintf(stderr, "Failed to calculate message differences\n");
    6672                return -1;
    6773        }
    6874
    69         if (mod->num_elements == 0) {
    70                 return 0;
     75        ret = mod->num_elements;
     76        if (ret == 0) {
     77                goto done;
    7178        }
    7279
     
    7582        }
    7683
    77         if (ldb_modify(ldb, mod) != 0) {
    78                 fprintf(stderr, "failed to modify %s - %s\n", 
     84        if (ldb_modify_ctrl(ldb, mod, req_ctrls) != LDB_SUCCESS) {
     85                fprintf(stderr, "failed to modify %s - %s\n",
    7986                        ldb_dn_get_linearized(msg1->dn), ldb_errstring(ldb));
    80                 return -1;
    81         }
    82 
    83         return mod->num_elements;
     87                ret = -1;
     88                goto done;
     89        }
     90
     91done:
     92        talloc_free(mod);
     93        return ret;
    8494}
    8595
     
    8999static struct ldb_message *msg_find(struct ldb_context *ldb,
    90100                                    struct ldb_message **msgs,
    91                                     int count,
     101                                    unsigned int count,
    92102                                    struct ldb_dn *dn)
    93103{
    94         int i;
     104        unsigned int i;
    95105        for (i=0;i<count;i++) {
    96106                if (ldb_dn_compare(dn, msgs[i]->dn) == 0) {
     
    105115*/
    106116static int merge_edits(struct ldb_context *ldb,
    107                        struct ldb_message **msgs1, int count1,
    108                        struct ldb_message **msgs2, int count2)
    109 {
    110         int i;
     117                       struct ldb_message **msgs1, unsigned int count1,
     118                       struct ldb_message **msgs2, unsigned int count2)
     119{
     120        unsigned int i;
    111121        struct ldb_message *msg;
    112         int ret = 0;
    113         int adds=0, modifies=0, deletes=0;
    114 
    115         if (ldb_transaction_start(ldb) != 0) {
     122        int ret;
     123        unsigned int adds=0, modifies=0, deletes=0;
     124        struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
     125        if (options->controls != NULL && req_ctrls == NULL) {
     126                fprintf(stderr, "parsing controls failed: %s\n", ldb_errstring(ldb));
     127                return -1;
     128        }
     129
     130        if (ldb_transaction_start(ldb) != LDB_SUCCESS) {
    116131                fprintf(stderr, "Failed to start transaction: %s\n", ldb_errstring(ldb));
    117132                return -1;
     
    125140                                ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]);
    126141                        }
    127                         if (ldb_add(ldb, msgs2[i]) != 0) {
     142                        if (ldb_add_ctrl(ldb, msgs2[i], req_ctrls) != LDB_SUCCESS) {
    128143                                fprintf(stderr, "failed to add %s - %s\n",
    129144                                        ldb_dn_get_linearized(msgs2[i]->dn),
     
    134149                        adds++;
    135150                } else {
    136                         if (modify_record(ldb, msg, msgs2[i]) > 0) {
    137                                 modifies++;
     151                        ret = modify_record(ldb, msg, msgs2[i], req_ctrls);
     152                        if (ret != -1) {
     153                                modifies += (unsigned int) ret;
     154                        } else {
     155                                return -1;
    138156                        }
    139157                }
     
    147165                                ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]);
    148166                        }
    149                         if (ldb_delete(ldb, msgs1[i]->dn) != 0) {
     167                        if (ldb_delete_ctrl(ldb, msgs1[i]->dn, req_ctrls) != LDB_SUCCESS) {
    150168                                fprintf(stderr, "failed to delete %s - %s\n",
    151169                                        ldb_dn_get_linearized(msgs1[i]->dn),
     
    158176        }
    159177
    160         if (ldb_transaction_commit(ldb) != 0) {
     178        if (ldb_transaction_commit(ldb) != LDB_SUCCESS) {
    161179                fprintf(stderr, "Failed to commit transaction: %s\n", ldb_errstring(ldb));
    162180                return -1;
    163181        }
    164182
    165         printf("# %d adds  %d modifies  %d deletes\n", adds, modifies, deletes);
    166 
    167         return ret;
     183        printf("# %u adds  %u modifies  %u deletes\n", adds, modifies, deletes);
     184
     185        return 0;
    168186}
    169187
     
    171189  save a set of messages as ldif to a file
    172190*/
    173 static int save_ldif(struct ldb_context *ldb, 
    174                      FILE *f, struct ldb_message **msgs, int count)
    175 {
    176         int i;
    177 
    178         fprintf(f, "# editing %d records\n", count);
     191static int save_ldif(struct ldb_context *ldb,
     192                     FILE *f, struct ldb_message **msgs, unsigned int count)
     193{
     194        unsigned int i;
     195
     196        fprintf(f, "# editing %u records\n", count);
    179197
    180198        for (i=0;i<count;i++) {
    181199                struct ldb_ldif ldif;
    182                 fprintf(f, "# record %d\n", i+1);
     200                fprintf(f, "# record %u\n", i+1);
    183201
    184202                ldif.changetype = LDB_CHANGETYPE_NONE;
     
    195213  edit the ldb search results in msgs using the user selected editor
    196214*/
    197 static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int count1,
    198                    const char *editor)
     215static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1,
     216                   unsigned int count1, const char *editor)
    199217{
    200218        int fd, ret;
     
    204222        struct ldb_ldif *ldif;
    205223        struct ldb_message **msgs2 = NULL;
    206         int count2 = 0;
     224        unsigned int count2 = 0;
    207225
    208226        /* write out the original set of messages to a temporary
     
    270288}
    271289
    272 static void usage(void)
     290static void usage(struct ldb_context *ldb)
    273291{
    274292        printf("Usage: ldbedit <options> <expression> <attributes ...>\n");
    275         ldb_cmdline_help("ldbedit", stdout);
    276         exit(1);
     293        ldb_cmdline_help(ldb, "ldbedit", stdout);
     294        exit(LDB_ERR_OPERATIONS_ERROR);
    277295}
    278296
     
    285303        const char *expression = "(|(objectClass=*)(distinguishedName=*))";
    286304        const char * const * attrs = NULL;
    287 
    288         ldb = ldb_init(NULL, NULL);
     305        TALLOC_CTX *mem_ctx = talloc_new(NULL);
     306        struct ldb_control **req_ctrls;
     307
     308        ldb = ldb_init(mem_ctx, NULL);
     309        if (ldb == NULL) {
     310                return LDB_ERR_OPERATIONS_ERROR;
     311        }
    289312
    290313        options = ldb_cmdline_process(ldb, argc, argv, usage);
    291314
    292315        /* the check for '=' is for compatibility with ldapsearch */
    293         if (options->argc > 0 && 
     316        if (options->argc > 0 &&
    294317            strchr(options->argv[0], '=')) {
    295318                expression = options->argv[0];
     
    304327        if (options->basedn != NULL) {
    305328                basedn = ldb_dn_new(ldb, ldb, options->basedn);
    306                 if ( ! ldb_dn_validate(basedn)) {
    307                         printf("Invalid Base DN format\n");
    308                         exit(1);
    309                 }
    310         }
    311 
    312         ret = ldb_search(ldb, ldb, &result, basedn, options->scope, attrs, "%s", expression);
     329                if (basedn == NULL) {
     330                        return LDB_ERR_OPERATIONS_ERROR;
     331                }
     332        }
     333
     334        req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
     335        if (options->controls != NULL &&  req_ctrls== NULL) {
     336                printf("parsing controls failed: %s\n", ldb_errstring(ldb));
     337                return LDB_ERR_OPERATIONS_ERROR;
     338        }
     339
     340        ret = ldb_search_ctrl(ldb, ldb, &result, basedn, options->scope, attrs, req_ctrls, "%s", expression);
    313341        if (ret != LDB_SUCCESS) {
    314342                printf("search failed - %s\n", ldb_errstring(ldb));
    315                 exit(1);
     343                return ret;
    316344        }
    317345
    318346        if (result->count == 0) {
    319347                printf("no matching records - cannot edit\n");
    320                 return 0;
    321         }
    322 
    323         do_edit(ldb, result->msgs, result->count, options->editor);
    324 
    325         if (result) {
    326                 ret = talloc_free(result);
    327                 if (ret == -1) {
    328                         fprintf(stderr, "talloc_free failed\n");
    329                         exit(1);
    330                 }
    331         }
    332 
    333         talloc_free(ldb);
    334         return 0;
    335 }
     348                talloc_free(mem_ctx);
     349                return LDB_SUCCESS;
     350        }
     351
     352        ret = do_edit(ldb, result->msgs, result->count, options->editor);
     353
     354        talloc_free(mem_ctx);
     355
     356        return ret == 0 ? LDB_SUCCESS : LDB_ERR_OPERATIONS_ERROR;
     357}
  • trunk/server/source4/lib/ldb/tools/ldbmodify.c

    r414 r745  
    3434#include "ldb.h"
    3535#include "tools/cmdline.h"
     36#include "ldbutil.h"
    3637
    37 static int failures;
     38static unsigned int failures;
     39static struct ldb_cmdline *options;
    3840
    39 static void usage(void)
     41static void usage(struct ldb_context *ldb)
    4042{
    4143        printf("Usage: ldbmodify <options> <ldif...>\n");
    4244        printf("Modifies a ldb based upon ldif change records\n\n");
    43         ldb_cmdline_help("ldbmodify", stdout);
    44         exit(1);
     45        ldb_cmdline_help(ldb, "ldbmodify", stdout);
     46        exit(LDB_ERR_OPERATIONS_ERROR);
    4547}
    4648
     
    4850  process modifies for one file
    4951*/
    50 static int process_file(struct ldb_context *ldb, FILE *f, int *count)
     52static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
    5153{
    5254        struct ldb_ldif *ldif;
    5355        int ret = LDB_SUCCESS;
    54        
     56        struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
     57
     58        if (options->controls != NULL &&  req_ctrls== NULL) {
     59                printf("parsing controls failed: %s\n", ldb_errstring(ldb));
     60                exit(LDB_ERR_OPERATIONS_ERROR);
     61        }
     62
    5563        while ((ldif = ldb_ldif_read_file(ldb, f))) {
    5664                switch (ldif->changetype) {
    5765                case LDB_CHANGETYPE_NONE:
    5866                case LDB_CHANGETYPE_ADD:
    59                         ret = ldb_add(ldb, ldif->msg);
     67                        ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls);
    6068                        break;
    6169                case LDB_CHANGETYPE_DELETE:
    62                         ret = ldb_delete(ldb, ldif->msg->dn);
     70                        ret = ldb_delete_ctrl(ldb, ldif->msg->dn,req_ctrls);
    6371                        break;
    6472                case LDB_CHANGETYPE_MODIFY:
    65                         ret = ldb_modify(ldb, ldif->msg);
     73                        ret = ldb_modify_ctrl(ldb, ldif->msg,req_ctrls);
    6674                        break;
    6775                }
    6876                if (ret != LDB_SUCCESS) {
    69                         fprintf(stderr, "ERR: \"%s\" on DN %s\n",
     77                        fprintf(stderr, "ERR: (%s) \"%s\" on DN %s\n",
     78                                ldb_strerror(ret),
    7079                                ldb_errstring(ldb), ldb_dn_get_linearized(ldif->msg->dn));
    7180                        failures++;
    7281                } else {
    7382                        (*count)++;
     83                        if (options->verbose) {
     84                                printf("Modified %s\n", ldb_dn_get_linearized(ldif->msg->dn));
     85                        }
    7486                }
    7587                ldb_ldif_read_free(ldb, ldif);
     
    8294{
    8395        struct ldb_context *ldb;
    84         int count=0;
    85         int i, ret=LDB_SUCCESS;
    86         struct ldb_cmdline *options;
     96        unsigned int i, count = 0;
     97        int ret = LDB_SUCCESS;
     98        TALLOC_CTX *mem_ctx = talloc_new(NULL);
    8799
    88         ldb = ldb_init(NULL, NULL);
     100        ldb = ldb_init(mem_ctx, NULL);
     101        if (ldb == NULL) {
     102                return LDB_ERR_OPERATIONS_ERROR;
     103        }
    89104
    90105        options = ldb_cmdline_process(ldb, argc, argv, usage);
     
    99114                        if (!f) {
    100115                                perror(fname);
    101                                 exit(1);
     116                                return LDB_ERR_OPERATIONS_ERROR;
    102117                        }
    103118                        ret = process_file(ldb, f, &count);
     
    106121        }
    107122
    108         talloc_free(ldb);
     123        talloc_free(mem_ctx);
    109124
    110         printf("Modified %d records with %d failures\n", count, failures);
     125        printf("Modified %u records with %u failures\n", count, failures);
    111126
    112127        return ret;
  • trunk/server/source4/lib/ldb/tools/ldbrename.c

    r414 r745  
    3737#include "tools/cmdline.h"
    3838
    39 static void usage(void)
     39static void usage(struct ldb_context *ldb)
    4040{
    4141        printf("Usage: ldbrename [<options>] <olddn> <newdn>\n");
    4242        printf("Renames records in a ldb\n\n");
    43         ldb_cmdline_help("ldbmodify", stdout);
    44         exit(1);
     43        ldb_cmdline_help(ldb, "ldbmodify", stdout);
     44        exit(LDB_ERR_OPERATIONS_ERROR);
    4545}
    4646
     
    5252        struct ldb_cmdline *options;
    5353        struct ldb_dn *dn1, *dn2;
     54        TALLOC_CTX *mem_ctx = talloc_new(NULL);
    5455
    55         ldb = ldb_init(NULL, NULL);
     56        ldb = ldb_init(mem_ctx, NULL);
     57        if (ldb == NULL) {
     58                return LDB_ERR_OPERATIONS_ERROR;
     59        }
    5660
    5761        options = ldb_cmdline_process(ldb, argc, argv, usage);
    5862
    5963        if (options->argc < 2) {
    60                 usage();
     64                usage(ldb);
    6165        }
    6266
    6367        dn1 = ldb_dn_new(ldb, ldb, options->argv[0]);
    6468        dn2 = ldb_dn_new(ldb, ldb, options->argv[1]);
    65 
    66         if ( ! ldb_dn_validate(dn1)) {
    67                 printf("Invalid DN1: %s\n", options->argv[0]);
    68                 return -1;
    69         }
    70         if ( ! ldb_dn_validate(dn2)) {
    71                 printf("Invalid DN2: %s\n", options->argv[1]);
    72                 return -1;
     69        if ((dn1 == NULL) || (dn2 == NULL)) {
     70                return LDB_ERR_OPERATIONS_ERROR;
    7371        }
    7472
    7573        ret = ldb_rename(ldb, dn1, dn2);
    76         if (ret == 0) {
     74        if (ret == LDB_SUCCESS) {
    7775                printf("Renamed 1 record\n");
    7876        } else  {
     
    8179        }
    8280
    83         talloc_free(ldb);
     81        talloc_free(mem_ctx);
    8482       
    8583        return ret;
  • trunk/server/source4/lib/ldb/tools/ldbsearch.c

    r414 r745  
    3232 */
    3333
    34 #include "ldb_includes.h"
     34#include "replace.h"
     35#include "system/filesys.h"
     36#include "system/time.h"
    3537#include "ldb.h"
    3638#include "tools/cmdline.h"
    3739
    38 static void usage(void)
     40static void usage(struct ldb_context *ldb)
    3941{
    4042        printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
    41         ldb_cmdline_help("ldbsearch", stdout);
    42         exit(1);
     43        ldb_cmdline_help(ldb, "ldbsearch", stdout);
     44        exit(LDB_ERR_OPERATIONS_ERROR);
    4345}
    4446
     
    5557
    5658        int sort;
    57         int num_stored;
     59        unsigned int num_stored;
    5860        struct ldb_message **store;
    59         int refs_stored;
     61        unsigned int refs_stored;
    6062        char **refs_store;
    6163
    62         int entries;
    63         int refs;
    64 
    65         int pending;
     64        unsigned int entries;
     65        unsigned int refs;
     66
     67        unsigned int pending;
    6668        int status;
    6769};
     
    132134{
    133135        struct search_context *sctx;
    134         int ret;
     136        int ret = LDB_SUCCESS;
    135137
    136138        sctx = talloc_get_type(req->context, struct search_context);
     
    173175
    174176        talloc_free(ares);
    175         if (ret) {
     177        if (ret != LDB_SUCCESS) {
    176178                return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
    177179        }
     
    192194        req = NULL;
    193195       
    194         sctx = talloc(ldb, struct search_context);
    195         if (!sctx) return -1;
     196        sctx = talloc_zero(ldb, struct search_context);
     197        if (!sctx) return LDB_ERR_OPERATIONS_ERROR;
    196198
    197199        sctx->ldb = ldb;
    198200        sctx->sort = options->sorted;
    199         sctx->num_stored = 0;
    200         sctx->refs_stored = 0;
    201         sctx->store = NULL;
    202201        sctx->req_ctrls = ldb_parse_control_strings(ldb, sctx, (const char **)options->controls);
    203202        if (options->controls != NULL &&  sctx->req_ctrls== NULL) {
    204203                printf("parsing controls failed: %s\n", ldb_errstring(ldb));
    205                 return -1;
    206         }
    207         sctx->entries = 0;
    208         sctx->refs = 0;
     204                return LDB_ERR_OPERATIONS_ERROR;
     205        }
    209206
    210207        if (basedn == NULL) {
     
    225222                talloc_free(sctx);
    226223                printf("allocating request failed: %s\n", ldb_errstring(ldb));
    227                 return -1;
     224                return ret;
    228225        }
    229226
     
    233230        if (ret != LDB_SUCCESS) {
    234231                printf("search failed - %s\n", ldb_errstring(ldb));
    235                 return -1;
     232                return ret;
    236233        }
    237234
    238235        ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    239         if (ret != LDB_SUCCESS) {
     236        if (ret != LDB_SUCCESS) {
    240237                printf("search error - %s\n", ldb_errstring(ldb));
    241                 return -1;
     238                return ret;
    242239        }
    243240
     
    246243
    247244        if (sctx->sort && (sctx->num_stored != 0 || sctx->refs != 0)) {
    248                 int i;
     245                unsigned int i;
    249246
    250247                if (sctx->num_stored) {
    251                         ldb_qsort(sctx->store, sctx->num_stored, sizeof(struct ldb_message *),
    252                                   ldb, (ldb_qsort_cmp_fn_t)do_compare_msg);
     248                        LDB_TYPESAFE_QSORT(sctx->store, sctx->num_stored, ldb, do_compare_msg);
    253249                }
    254250                for (i = 0; i < sctx->num_stored; i++) {
     
    261257        }
    262258
    263         printf("# returned %d records\n# %d entries\n# %d referrals\n",
     259        printf("# returned %u records\n# %u entries\n# %u referrals\n",
    264260                sctx->entries + sctx->refs, sctx->entries, sctx->refs);
    265261
     
    267263        talloc_free(req);
    268264
    269         return 0;
     265        return LDB_SUCCESS;
    270266}
    271267
     
    278274        int ret = -1;
    279275        const char *expression = "(|(objectClass=*)(distinguishedName=*))";
    280 
    281         ldb = ldb_init(NULL, NULL);
     276        TALLOC_CTX *mem_ctx = talloc_new(NULL);
     277
     278        ldb = ldb_init(mem_ctx, NULL);
    282279        if (ldb == NULL) {
    283                 return -1;
     280                return LDB_ERR_OPERATIONS_ERROR;
    284281        }
    285282
     
    301298        if (options->basedn != NULL) {
    302299                basedn = ldb_dn_new(ldb, ldb, options->basedn);
    303                 if ( ! ldb_dn_validate(basedn)) {
    304                         fprintf(stderr, "Invalid Base DN format\n");
    305                         exit(1);
     300                if (basedn == NULL) {
     301                        return LDB_ERR_OPERATIONS_ERROR;
    306302                }
    307303        }
     
    310306                char line[1024];
    311307                while (fgets(line, sizeof(line), stdin)) {
    312                         if (do_search(ldb, basedn, options, line, attrs) == -1) {
    313                                 ret = -1;
    314                         }
     308                        ret = do_search(ldb, basedn, options, line, attrs);
    315309                }
    316310        } else {
     
    318312        }
    319313
    320         talloc_free(ldb);
     314        talloc_free(mem_ctx);
     315
    321316        return ret;
    322317}
  • trunk/server/source4/lib/ldb/tools/ldbtest.c

    r414 r745  
    3232 */
    3333
    34 #include "ldb_includes.h"
     34#include "replace.h"
     35#include "system/filesys.h"
     36#include "system/time.h"
    3537#include "ldb.h"
    3638#include "tools/cmdline.h"
    3739
    38 static struct timeval tp1,tp2;
     40static struct timespec tp1,tp2;
    3941static struct ldb_cmdline *options;
    4042
    4143static void _start_timer(void)
    4244{
    43         gettimeofday(&tp1,NULL);
     45        if (clock_gettime(CUSTOM_CLOCK_MONOTONIC, &tp1) != 0) {
     46                clock_gettime(CLOCK_REALTIME, &tp1);
     47        }
    4448}
    4549
    4650static double _end_timer(void)
    4751{
    48         gettimeofday(&tp2,NULL);
     52        if (clock_gettime(CUSTOM_CLOCK_MONOTONIC, &tp2) != 0) {
     53                clock_gettime(CLOCK_REALTIME, &tp2);
     54        }
    4955        return((tp2.tv_sec - tp1.tv_sec) +
    50                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
     56               (tp2.tv_nsec - tp1.tv_nsec)*1.0e-9);
    5157}
    5258
    5359static void add_records(struct ldb_context *ldb,
    5460                        struct ldb_dn *basedn,
    55                         int count)
     61                        unsigned int count)
    5662{
    5763        struct ldb_message msg;
    58         int i;
     64        unsigned int i;
    5965
    6066#if 0
    6167        if (ldb_lock(ldb, "transaction") != 0) {
    6268                printf("transaction lock failed\n");
    63                 exit(1);
     69                exit(LDB_ERR_OPERATIONS_ERROR);
    6470        }
    6571#endif
     
    123129                if (ldb_add(ldb, &msg) != 0) {
    124130                        printf("Add of %s failed - %s\n", name, ldb_errstring(ldb));
    125                         exit(1);
     131                        exit(LDB_ERR_OPERATIONS_ERROR);
    126132                }
    127133
     
    134140        if (ldb_unlock(ldb, "transaction") != 0) {
    135141                printf("transaction unlock failed\n");
    136                 exit(1);
     142                exit(LDB_ERR_OPERATIONS_ERROR);
    137143        }
    138144#endif
     
    142148static void modify_records(struct ldb_context *ldb,
    143149                           struct ldb_dn *basedn,
    144                            int count)
     150                           unsigned int count)
    145151{
    146152        struct ldb_message msg;
    147         int i;
     153        unsigned int i;
    148154
    149155        for (i=0;i<count;i++) {
     
    180186                if (ldb_modify(ldb, &msg) != 0) {
    181187                        printf("Modify of %s failed - %s\n", name, ldb_errstring(ldb));
    182                         exit(1);
     188                        exit(LDB_ERR_OPERATIONS_ERROR);
    183189                }
    184190
     
    195201static void delete_records(struct ldb_context *ldb,
    196202                           struct ldb_dn *basedn,
    197                            int count)
    198 {
    199         int i;
     203                           unsigned int count)
     204{
     205        unsigned int i;
    200206
    201207        for (i=0;i<count;i++) {
     
    210216                if (ldb_delete(ldb, dn) != 0) {
    211217                        printf("Delete of %s failed - %s\n", ldb_dn_get_linearized(dn), ldb_errstring(ldb));
    212                         exit(1);
     218                        exit(LDB_ERR_OPERATIONS_ERROR);
    213219                }
    214220                talloc_free(name);
     
    218224}
    219225
    220 static void search_uid(struct ldb_context *ldb, struct ldb_dn *basedn, int nrecords, int nsearches)
    221 {
    222         int i;
     226static void search_uid(struct ldb_context *ldb, struct ldb_dn *basedn,
     227                       unsigned int nrecords, unsigned int nsearches)
     228{
     229        unsigned int i;
    223230
    224231        for (i=0;i<nsearches;i++) {
     
    233240                if (ret != LDB_SUCCESS || (uid < nrecords && res->count != 1)) {
    234241                        printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb));
    235                         exit(1);
     242                        exit(LDB_ERR_OPERATIONS_ERROR);
    236243                }
    237244
    238245                if (uid >= nrecords && res->count > 0) {
    239246                        printf("Found %s !? - %d\n", expr, ret);
    240                         exit(1);
     247                        exit(LDB_ERR_OPERATIONS_ERROR);
    241248                }
    242249
    243                 printf("testing uid %d/%d - %d  \r", i, uid, res->count);
     250                printf("Testing uid %d/%d - %d  \r", i, uid, res->count);
    244251                fflush(stdout);
    245252
     
    251258}
    252259
    253 static void start_test(struct ldb_context *ldb, int nrecords, int nsearches)
     260static void start_test(struct ldb_context *ldb, unsigned int nrecords,
     261                       unsigned int nsearches)
    254262{
    255263        struct ldb_dn *basedn;
     
    257265        basedn = ldb_dn_new(ldb, ldb, options->basedn);
    258266        if ( ! ldb_dn_validate(basedn)) {
    259                 printf("Invalid base DN\n");
    260                 exit(1);
     267                printf("Invalid base DN format\n");
     268                exit(LDB_ERR_INVALID_DN_SYNTAX);
    261269        }
    262270
     
    323331        if (ldb_add(*ldb, msg) != 0) {
    324332                printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb));
    325                 exit(1);
     333                exit(LDB_ERR_OPERATIONS_ERROR);
    326334        }
    327335
     
    338346        if (ldb_add(*ldb, msg) != 0) {
    339347                printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb));
    340                 exit(1);
     348                exit(LDB_ERR_OPERATIONS_ERROR);
    341349        }
    342350
    343351        if (talloc_free(*ldb) != 0) {
    344352                printf("failed to free/close ldb database");
    345                 exit(1);
     353                exit(LDB_ERR_OPERATIONS_ERROR);
    346354        }
    347355
     
    351359        if (ret != 0) {
    352360                printf("failed to connect to %s\n", options->url);
    353                 exit(1);
     361                exit(LDB_ERR_OPERATIONS_ERROR);
    354362        }
    355363
    356364        basedn = ldb_dn_new(*ldb, *ldb, options->basedn);
     365        msg->dn = basedn;
     366        ldb_dn_add_child_fmt(msg->dn, "cn=test");
    357367
    358368        ret = ldb_search(*ldb, *ldb, &res, basedn, LDB_SCOPE_SUBTREE, NULL, "uid=test");
    359369        if (ret != LDB_SUCCESS) {
    360370                printf("Search with (uid=test) filter failed!\n");
    361                 exit(1);
     371                exit(LDB_ERR_OPERATIONS_ERROR);
    362372        }
    363373        if(res->count != 1) {
    364374                printf("Should have found 1 record - found %d\n", res->count);
    365                 exit(1);
     375                exit(LDB_ERR_OPERATIONS_ERROR);
    366376        }
    367377
     
    371381            ldb_delete(*ldb, indexlist) != 0) {
    372382                printf("cleanup failed - %s\n", ldb_errstring(*ldb));
    373                 exit(1);
     383                exit(LDB_ERR_OPERATIONS_ERROR);
    374384        }
    375385
     
    378388
    379389
    380 static void usage(void)
     390static void usage(struct ldb_context *ldb)
    381391{
    382392        printf("Usage: ldbtest <options>\n");
     
    387397        printf("\n");
    388398        printf("tests ldb API\n\n");
    389         exit(1);
     399        exit(LDB_ERR_OPERATIONS_ERROR);
    390400}
    391401
     
    396406
    397407        ldb = ldb_init(mem_ctx, NULL);
     408        if (ldb == NULL) {
     409                return LDB_ERR_OPERATIONS_ERROR;
     410        }
    398411
    399412        options = ldb_cmdline_process(ldb, argc, argv, usage);
     
    410423               options->num_records, options->num_searches);
    411424
    412         start_test(ldb, options->num_records, options->num_searches);
     425        start_test(ldb,
     426                   (unsigned int) options->num_records,
     427                   (unsigned int) options->num_searches);
    413428
    414429        start_test_index(&ldb);
     
    416431        talloc_free(mem_ctx);
    417432
    418         return 0;
    419 }
     433        return LDB_SUCCESS;
     434}
  • trunk/server/source4/lib/ldb/web/index.html

    r414 r745  
    5151<h2>Discussion and bug reports</h2>
    5252
    53 ldb does not currently have its own mailing list or bug tracking
    54 system. For now, please use the <a
    55 href="https://lists.samba.org/mailman/listinfo/samba-technical">samba-technical</a>
    56 mailing list or the <a href="https://lists.samba.org/mailman/listinfo/ldb">ldb</a>
    57 mailing list, and the <a href="http://bugzilla.samba.org/">Samba bugzilla</a> bug tracking system.
     53ldb does not have its own mailing list or bug tracking system. Please
     54use
     55the <a href="https://lists.samba.org/mailman/listinfo/samba-technical">samba-technical</a>
     56mailing list, and the <a href="http://bugzilla.samba.org/">Samba
     57bugzilla</a> bug tracking system.
    5858
    5959<h2>Download</h2>
    6060
    61 You can download the latest release either via rsync or thtough git.<br>
    62 <br>
    63 To fetch via git see the following guide:<br>
     61You can download the latest release here:<br>
     62 <a href="http://samba.org/ftp/pub/ldb">http://samba.org/ftp/pub/ldb</a>
     63
     64Alternatively, you can fetch via git. See the following guide:<br>
    6465<a href="http://wiki.samba.org/index.php/Using_Git_for_Samba_Development">Using Git for Samba Development</a><br>
    65 Once you have cloned the tree switch to the v4-0-test branch and cd into the source/lib/ldb directory.<br>
    66 <br>
    67 To fetch via rsync use these commands:
    68 
    69 <pre>
    70   rsync -Pavz samba.org::ftp/unpacked/ldb .
    71   rsync -Pavz samba.org::ftp/unpacked/tdb .
    72   rsync -Pavz samba.org::ftp/unpacked/talloc .
    73   rsync -Pavz samba.org::ftp/unpacked/libreplace .
    74 </pre>
    75 
    76 and build in ldb. It will find the other libraries in the directory
    77 above automatically.
    7866
    7967<hr>
  • trunk/server/source4/lib/messaging/irpc.h

    r414 r745  
    2525#include "lib/messaging/messaging.h"
    2626#include "librpc/gen_ndr/irpc.h"
    27 #include "librpc/gen_ndr/server_id.h"
    2827
    2928/*
     
    3635        struct ndr_pull *ndr;
    3736        bool defer_reply;
     37        bool no_reply;
    3838        struct messaging_context *msg_ctx;
    3939        struct irpc_list *irpc;
     
    4343
    4444/* don't allow calls to take too long */
    45 #define IRPC_CALL_TIMEOUT 10
     45#define IRPC_CALL_TIMEOUT       10
     46/* wait for the calls as long as it takes */
     47#define IRPC_CALL_TIMEOUT_INF   0
    4648
    4749
     
    5557                          (irpc_function_t)function, private_data)
    5658
    57 /* make a irpc call */
    58 #define IRPC_CALL(msg_ctx, server_id, pipename, funcname, ptr, ctx) \
    59    irpc_call(msg_ctx, server_id, &ndr_table_ ## pipename, NDR_ ## funcname, ptr, ctx)
    60 
    61 #define IRPC_CALL_SEND(msg_ctx, server_id, pipename, funcname, ptr, ctx) \
    62    irpc_call_send(msg_ctx, server_id, &ndr_table_ ## pipename, NDR_ ## funcname, ptr, ctx)
    63 
    64 
    65 /*
    66   a pending irpc call
    67 */
    68 struct irpc_request {
    69         struct messaging_context *msg_ctx;
    70         const struct ndr_interface_table *table;
    71         int callnum;
    72         int callid;
    73         void *r;
    74         NTSTATUS status;
    75         bool done;
    76         bool reject_free;
    77         TALLOC_CTX *mem_ctx;
    78         struct {
    79                 void (*fn)(struct irpc_request *);
    80                 void *private_data;
    81         } async;
    82 };
    83 
    84 struct loadparm_context;
    85 
    86 typedef void (*msg_callback_t)(struct messaging_context *msg, void *private_data,
    87                                uint32_t msg_type,
    88                                struct server_id server_id, DATA_BLOB *data);
    89 
    90 NTSTATUS messaging_send(struct messaging_context *msg, struct server_id server,
    91                         uint32_t msg_type, DATA_BLOB *data);
    92 NTSTATUS messaging_register(struct messaging_context *msg, void *private_data,
    93                             uint32_t msg_type,
    94                             msg_callback_t fn);
    95 NTSTATUS messaging_register_tmp(struct messaging_context *msg, void *private_data,
    96                                 msg_callback_t fn, uint32_t *msg_type);
    97 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
    98                                          const char *dir,
    99                                          struct server_id server_id,
    100                                          struct smb_iconv_convenience *iconv_convenience,
    101                                          struct tevent_context *ev);
    102 struct messaging_context *messaging_client_init(TALLOC_CTX *mem_ctx,
    103                                          const char *dir,
    104                                          struct smb_iconv_convenience *iconv_convenience,
    105                                          struct tevent_context *ev);
    106 NTSTATUS messaging_send_ptr(struct messaging_context *msg, struct server_id server,
    107                             uint32_t msg_type, void *ptr);
    108 void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void *private_data);
    109 
    110 
    111 
     59struct ndr_interface_table;
    11260
    11361NTSTATUS irpc_register(struct messaging_context *msg_ctx,
    11462                       const struct ndr_interface_table *table,
    11563                       int call, irpc_function_t fn, void *private_data);
    116 struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx,
    117                                     struct server_id server_id,
    118                                     const struct ndr_interface_table *table,
    119                                     int callnum, void *r, TALLOC_CTX *ctx);
    120 NTSTATUS irpc_call_recv(struct irpc_request *irpc);
    121 NTSTATUS irpc_call(struct messaging_context *msg_ctx,
    122                    struct server_id server_id,
    123                    const struct ndr_interface_table *table,
    124                    int callnum, void *r, TALLOC_CTX *ctx);
     64
     65struct dcerpc_binding_handle *irpc_binding_handle(TALLOC_CTX *mem_ctx,
     66                                        struct messaging_context *msg_ctx,
     67                                        struct server_id server_id,
     68                                        const struct ndr_interface_table *table);
     69struct dcerpc_binding_handle *irpc_binding_handle_by_name(TALLOC_CTX *mem_ctx,
     70                                        struct messaging_context *msg_ctx,
     71                                        const char *dest_task,
     72                                        const struct ndr_interface_table *table);
     73void irpc_binding_handle_add_security_token(struct dcerpc_binding_handle *h,
     74                                            struct security_token *token);
    12575
    12676NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name);
     
    12878void irpc_remove_name(struct messaging_context *msg_ctx, const char *name);
    12979NTSTATUS irpc_send_reply(struct irpc_message *m, NTSTATUS status);
    130 struct server_id messaging_get_server_id(struct messaging_context *msg_ctx);
    13180
    13281#endif
  • trunk/server/source4/lib/messaging/messaging.c

    r414 r745  
    2828#include "librpc/gen_ndr/ndr_irpc.h"
    2929#include "lib/messaging/irpc.h"
    30 #include "tdb_wrap.h"
     30#include "lib/util/tdb_wrap.h"
    3131#include "../lib/util/unix_privs.h"
    3232#include "librpc/rpc/dcerpc.h"
    33 #include "../tdb/include/tdb.h"
     33#include <tdb.h>
    3434#include "../lib/util/util_tdb.h"
    3535#include "cluster/cluster.h"
     36#include "../lib/util/tevent_ntstatus.h"
    3637
    3738/* change the message version with any incompatible changes in the protocol */
    3839#define MESSAGING_VERSION 1
     40
     41/*
     42  a pending irpc call
     43*/
     44struct irpc_request {
     45        struct messaging_context *msg_ctx;
     46        int callid;
     47        struct {
     48                void (*handler)(struct irpc_request *irpc, struct irpc_message *m);
     49                void *private_data;
     50        } incoming;
     51};
    3952
    4053struct messaging_context {
     
    4861        struct messaging_rec *pending;
    4962        struct messaging_rec *retry_queue;
    50         struct smb_iconv_convenience *iconv_convenience;
    5163        struct irpc_list *irpc;
    5264        struct idr_context *idr;
     
    99111{
    100112        DEBUG(1,("INFO: Received PING message from server %u.%u [%.*s]\n",
    101                  (uint_t)src.node, (uint_t)src.id, (int)data->length,
     113                 (unsigned int)src.node, (unsigned int)src.id, (int)data->length,
    102114                 data->data?(const char *)data->data:""));
    103115        messaging_send(msg, src, MSG_PONG, data);
     
    120132static char *messaging_path(struct messaging_context *msg, struct server_id server_id)
    121133{
    122         return talloc_asprintf(msg, "%s/msg.%s", msg->base_path,
    123                                cluster_id_string(msg, server_id));
     134        TALLOC_CTX *tmp_ctx = talloc_new(msg);
     135        const char *id = cluster_id_string(tmp_ctx, server_id);
     136        char *s;
     137        if (id == NULL) {
     138                return NULL;
     139        }
     140        s = talloc_asprintf(msg, "%s/msg.%s", msg->base_path, id);
     141        talloc_steal(s, tmp_ctx);
     142        return s;
    124143}
    125144
     
    262281                rec->retries = 0;
    263282                if (!NT_STATUS_IS_OK(status)) {
     283                        TALLOC_CTX *tmp_ctx = talloc_new(msg);
    264284                        DEBUG(1,("messaging: Lost message from %s to %s of type %u - %s\n",
    265                                  cluster_id_string(debug_ctx(), rec->header->from),
    266                                  cluster_id_string(debug_ctx(), rec->header->to),
     285                                 cluster_id_string(tmp_ctx, rec->header->from),
     286                                 cluster_id_string(tmp_ctx, rec->header->to),
    267287                                 rec->header->msg_type,
    268288                                 nt_errstr(status)));
     289                        talloc_free(tmp_ctx);
    269290                }
    270291                DLIST_REMOVE(msg->pending, rec);
     
    441462*/
    442463NTSTATUS messaging_send(struct messaging_context *msg, struct server_id server,
    443                         uint32_t msg_type, DATA_BLOB *data)
     464                        uint32_t msg_type, const DATA_BLOB *data)
    444465{
    445466        struct messaging_rec *rec;
     
    536557                                         const char *dir,
    537558                                         struct server_id server_id,
    538                                          struct smb_iconv_convenience *iconv_convenience,
    539559                                         struct tevent_context *ev)
    540560{
     
    565585        msg->path          = messaging_path(msg, server_id);
    566586        msg->server_id     = server_id;
    567         msg->iconv_convenience = iconv_convenience;
    568587        msg->idr           = idr_init(msg);
    569588        msg->dispatch_tree = idr_init(msg);
     
    600619        msg->event.fde  = event_add_fd(ev, msg, socket_get_fd(msg->sock),
    601620                                       EVENT_FD_READ, messaging_handler, msg);
     621        tevent_fd_set_auto_close(msg->event.fde);
    602622
    603623        talloc_set_destructor(msg, messaging_destructor);
     
    615635struct messaging_context *messaging_client_init(TALLOC_CTX *mem_ctx,
    616636                                                const char *dir,
    617                                                 struct smb_iconv_convenience *iconv_convenience,
    618637                                                struct tevent_context *ev)
    619638{
     
    621640        ZERO_STRUCT(id);
    622641        id.id = random() % 0x10000000;
    623         return messaging_init(mem_ctx, dir, id, iconv_convenience, ev);
     642        return messaging_init(mem_ctx, dir, id, ev);
    624643}
    625644/*
     
    673692{
    674693        struct irpc_request *irpc;
    675         enum ndr_err_code ndr_err;
    676694
    677695        irpc = (struct irpc_request *)idr_find(msg_ctx->idr, m->header.callid);
    678696        if (irpc == NULL) return;
    679697
    680         /* parse the reply data */
    681         ndr_err = irpc->table->calls[irpc->callnum].ndr_pull(m->ndr, NDR_OUT, irpc->r);
    682         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    683                 irpc->status = m->header.status;
    684                 talloc_steal(irpc->mem_ctx, m);
    685         } else {
    686                 irpc->status = ndr_map_error2ntstatus(ndr_err);
    687                 talloc_steal(irpc, m);
    688         }
    689         irpc->done = true;
    690         if (irpc->async.fn) {
    691                 irpc->async.fn(irpc);
    692         }
     698        irpc->incoming.handler(irpc, m);
    693699}
    694700
     
    705711
    706712        /* setup the reply */
    707         push = ndr_push_init_ctx(m->ndr, m->msg_ctx->iconv_convenience);
     713        push = ndr_push_init_ctx(m->ndr);
    708714        if (push == NULL) {
    709715                status = NT_STATUS_NO_MEMORY;
     
    712718
    713719        m->header.flags |= IRPC_FLAG_REPLY;
     720        m->header.creds.token= NULL;
    714721
    715722        /* construct the packet */
     
    764771        if (r == NULL) goto failed;
    765772
     773        m->ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
     774
    766775        /* parse the request data */
    767776        ndr_err = i->table->calls[i->callnum].ndr_pull(m->ndr, NDR_IN, r);
     
    771780        m->private_data= i->private_data;
    772781        m->defer_reply = false;
     782        m->no_reply    = false;
    773783        m->msg_ctx     = msg_ctx;
    774784        m->irpc        = i;
     
    778788        m->header.status = i->fn(m, r);
    779789
     790        if (m->no_reply) {
     791                /* the server function won't ever be replying to this request */
     792                talloc_free(m);
     793                return;
     794        }
     795
    780796        if (m->defer_reply) {
    781797                /* the server function has asked to defer the reply to later */
     
    805821        m->from = src;
    806822
    807         m->ndr = ndr_pull_init_blob(packet, m, msg_ctx->iconv_convenience);
     823        m->ndr = ndr_pull_init_blob(packet, m);
    808824        if (m->ndr == NULL) goto failed;
    809825
     
    835851        }
    836852
    837         if (irpc->reject_free) {
    838                 return -1;
    839         }
    840853        return 0;
    841 }
    842 
    843 /*
    844   timeout a irpc request
    845 */
    846 static void irpc_timeout(struct tevent_context *ev, struct tevent_timer *te,
    847                          struct timeval t, void *private_data)
    848 {
    849         struct irpc_request *irpc = talloc_get_type(private_data, struct irpc_request);
    850         irpc->status = NT_STATUS_IO_TIMEOUT;
    851         irpc->done = true;
    852         if (irpc->async.fn) {
    853                 irpc->async.fn(irpc);
    854         }
    855 }
    856 
    857 
    858 /*
    859   make a irpc call - async send
    860 */
    861 struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx,
    862                                     struct server_id server_id,
    863                                     const struct ndr_interface_table *table,
    864                                     int callnum, void *r, TALLOC_CTX *ctx)
    865 {
    866         struct irpc_header header;
    867         struct ndr_push *ndr;
    868         NTSTATUS status;
    869         DATA_BLOB packet;
    870         struct irpc_request *irpc;
    871         enum ndr_err_code ndr_err;
    872 
    873         irpc = talloc(msg_ctx, struct irpc_request);
    874         if (irpc == NULL) goto failed;
    875 
    876         irpc->msg_ctx  = msg_ctx;
    877         irpc->table    = table;
    878         irpc->callnum  = callnum;
    879         irpc->callid   = idr_get_new(msg_ctx->idr, irpc, UINT16_MAX);
    880         if (irpc->callid == -1) goto failed;
    881         irpc->r        = r;
    882         irpc->done     = false;
    883         irpc->async.fn = NULL;
    884         irpc->mem_ctx  = ctx;
    885         irpc->reject_free = false;
    886 
    887         talloc_set_destructor(irpc, irpc_destructor);
    888 
    889         /* setup the header */
    890         header.uuid = table->syntax_id.uuid;
    891 
    892         header.if_version = table->syntax_id.if_version;
    893         header.callid     = irpc->callid;
    894         header.callnum    = callnum;
    895         header.flags      = 0;
    896         header.status     = NT_STATUS_OK;
    897 
    898         /* construct the irpc packet */
    899         ndr = ndr_push_init_ctx(irpc, msg_ctx->iconv_convenience);
    900         if (ndr == NULL) goto failed;
    901 
    902         ndr_err = ndr_push_irpc_header(ndr, NDR_SCALARS|NDR_BUFFERS, &header);
    903         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;
    904 
    905         ndr_err = table->calls[callnum].ndr_push(ndr, NDR_IN, r);
    906         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;
    907 
    908         /* and send it */
    909         packet = ndr_push_blob(ndr);
    910         status = messaging_send(msg_ctx, server_id, MSG_IRPC, &packet);
    911         if (!NT_STATUS_IS_OK(status)) goto failed;
    912 
    913         event_add_timed(msg_ctx->event.ev, irpc,
    914                         timeval_current_ofs(IRPC_CALL_TIMEOUT, 0),
    915                         irpc_timeout, irpc);
    916 
    917         talloc_free(ndr);
    918         return irpc;
    919 
    920 failed:
    921         talloc_free(irpc);
    922         return NULL;
    923 }
    924 
    925 /*
    926   wait for a irpc reply
    927 */
    928 NTSTATUS irpc_call_recv(struct irpc_request *irpc)
    929 {
    930         NTSTATUS status;
    931 
    932         NT_STATUS_HAVE_NO_MEMORY(irpc);
    933 
    934         irpc->reject_free = true;
    935 
    936         while (!irpc->done) {
    937                 if (event_loop_once(irpc->msg_ctx->event.ev) != 0) {
    938                         return NT_STATUS_CONNECTION_DISCONNECTED;
    939                 }
    940         }
    941 
    942         irpc->reject_free = false;
    943 
    944         status = irpc->status;
    945         talloc_free(irpc);
    946         return status;
    947 }
    948 
    949 /*
    950   perform a synchronous irpc request
    951 */
    952 NTSTATUS irpc_call(struct messaging_context *msg_ctx,
    953                    struct server_id server_id,
    954                    const struct ndr_interface_table *table,
    955                    int callnum, void *r,
    956                    TALLOC_CTX *mem_ctx)
    957 {
    958         struct irpc_request *irpc = irpc_call_send(msg_ctx, server_id,
    959                                                    table, callnum, r, mem_ctx);
    960         return irpc_call_recv(irpc);
    961854}
    962855
     
    11171010        return msg_ctx->server_id;
    11181011}
     1012
     1013struct irpc_bh_state {
     1014        struct messaging_context *msg_ctx;
     1015        struct server_id server_id;
     1016        const struct ndr_interface_table *table;
     1017        uint32_t timeout;
     1018        struct security_token *token;
     1019};
     1020
     1021static bool irpc_bh_is_connected(struct dcerpc_binding_handle *h)
     1022{
     1023        struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
     1024                                   struct irpc_bh_state);
     1025
     1026        if (!hs->msg_ctx) {
     1027                return false;
     1028        }
     1029
     1030        return true;
     1031}
     1032
     1033static uint32_t irpc_bh_set_timeout(struct dcerpc_binding_handle *h,
     1034                                    uint32_t timeout)
     1035{
     1036        struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
     1037                                   struct irpc_bh_state);
     1038        uint32_t old = hs->timeout;
     1039
     1040        hs->timeout = timeout;
     1041
     1042        return old;
     1043}
     1044
     1045struct irpc_bh_raw_call_state {
     1046        struct irpc_request *irpc;
     1047        uint32_t opnum;
     1048        DATA_BLOB in_data;
     1049        DATA_BLOB in_packet;
     1050        DATA_BLOB out_data;
     1051};
     1052
     1053static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc,
     1054                                              struct irpc_message *m);
     1055
     1056static struct tevent_req *irpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
     1057                                                struct tevent_context *ev,
     1058                                                struct dcerpc_binding_handle *h,
     1059                                                const struct GUID *object,
     1060                                                uint32_t opnum,
     1061                                                uint32_t in_flags,
     1062                                                const uint8_t *in_data,
     1063                                                size_t in_length)
     1064{
     1065        struct irpc_bh_state *hs =
     1066                dcerpc_binding_handle_data(h,
     1067                struct irpc_bh_state);
     1068        struct tevent_req *req;
     1069        struct irpc_bh_raw_call_state *state;
     1070        bool ok;
     1071        struct irpc_header header;
     1072        struct ndr_push *ndr;
     1073        NTSTATUS status;
     1074        enum ndr_err_code ndr_err;
     1075
     1076        req = tevent_req_create(mem_ctx, &state,
     1077                                struct irpc_bh_raw_call_state);
     1078        if (req == NULL) {
     1079                return NULL;
     1080        }
     1081        state->opnum = opnum;
     1082        state->in_data.data = discard_const_p(uint8_t, in_data);
     1083        state->in_data.length = in_length;
     1084
     1085        ok = irpc_bh_is_connected(h);
     1086        if (!ok) {
     1087                tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
     1088                return tevent_req_post(req, ev);
     1089        }
     1090
     1091        state->irpc = talloc_zero(state, struct irpc_request);
     1092        if (tevent_req_nomem(state->irpc, req)) {
     1093                return tevent_req_post(req, ev);
     1094        }
     1095
     1096        state->irpc->msg_ctx  = hs->msg_ctx;
     1097        state->irpc->callid   = idr_get_new(hs->msg_ctx->idr,
     1098                                            state->irpc, UINT16_MAX);
     1099        if (state->irpc->callid == -1) {
     1100                tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
     1101                return tevent_req_post(req, ev);
     1102        }
     1103        state->irpc->incoming.handler = irpc_bh_raw_call_incoming_handler;
     1104        state->irpc->incoming.private_data = req;
     1105
     1106        talloc_set_destructor(state->irpc, irpc_destructor);
     1107
     1108        /* setup the header */
     1109        header.uuid = hs->table->syntax_id.uuid;
     1110
     1111        header.if_version = hs->table->syntax_id.if_version;
     1112        header.callid     = state->irpc->callid;
     1113        header.callnum    = state->opnum;
     1114        header.flags      = 0;
     1115        header.status     = NT_STATUS_OK;
     1116        header.creds.token= hs->token;
     1117
     1118        /* construct the irpc packet */
     1119        ndr = ndr_push_init_ctx(state->irpc);
     1120        if (tevent_req_nomem(ndr, req)) {
     1121                return tevent_req_post(req, ev);
     1122        }
     1123
     1124        ndr_err = ndr_push_irpc_header(ndr, NDR_SCALARS|NDR_BUFFERS, &header);
     1125        status = ndr_map_error2ntstatus(ndr_err);
     1126        if (!NT_STATUS_IS_OK(status)) {
     1127                tevent_req_nterror(req, status);
     1128                return tevent_req_post(req, ev);
     1129        }
     1130
     1131        ndr_err = ndr_push_bytes(ndr, in_data, in_length);
     1132        status = ndr_map_error2ntstatus(ndr_err);
     1133        if (!NT_STATUS_IS_OK(status)) {
     1134                tevent_req_nterror(req, status);
     1135                return tevent_req_post(req, ev);
     1136        }
     1137
     1138        /* and send it */
     1139        state->in_packet = ndr_push_blob(ndr);
     1140        status = messaging_send(hs->msg_ctx, hs->server_id,
     1141                                MSG_IRPC, &state->in_packet);
     1142        if (!NT_STATUS_IS_OK(status)) {
     1143                tevent_req_nterror(req, status);
     1144                return tevent_req_post(req, ev);
     1145        }
     1146
     1147        if (hs->timeout != IRPC_CALL_TIMEOUT_INF) {
     1148                /* set timeout-callback in case caller wants that */
     1149                ok = tevent_req_set_endtime(req, ev, timeval_current_ofs(hs->timeout, 0));
     1150                if (!ok) {
     1151                        return tevent_req_post(req, ev);
     1152                }
     1153        }
     1154
     1155        return req;
     1156}
     1157
     1158static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc,
     1159                                              struct irpc_message *m)
     1160{
     1161        struct tevent_req *req =
     1162                talloc_get_type_abort(irpc->incoming.private_data,
     1163                struct tevent_req);
     1164        struct irpc_bh_raw_call_state *state =
     1165                tevent_req_data(req,
     1166                struct irpc_bh_raw_call_state);
     1167
     1168        talloc_steal(state, m);
     1169
     1170        if (!NT_STATUS_IS_OK(m->header.status)) {
     1171                tevent_req_nterror(req, m->header.status);
     1172                return;
     1173        }
     1174
     1175        state->out_data = data_blob_talloc(state,
     1176                m->ndr->data + m->ndr->offset,
     1177                m->ndr->data_size - m->ndr->offset);
     1178        if ((m->ndr->data_size - m->ndr->offset) > 0 && !state->out_data.data) {
     1179                tevent_req_nomem(NULL, req);
     1180                return;
     1181        }
     1182
     1183        tevent_req_done(req);
     1184}
     1185
     1186static NTSTATUS irpc_bh_raw_call_recv(struct tevent_req *req,
     1187                                        TALLOC_CTX *mem_ctx,
     1188                                        uint8_t **out_data,
     1189                                        size_t *out_length,
     1190                                        uint32_t *out_flags)
     1191{
     1192        struct irpc_bh_raw_call_state *state =
     1193                tevent_req_data(req,
     1194                struct irpc_bh_raw_call_state);
     1195        NTSTATUS status;
     1196
     1197        if (tevent_req_is_nterror(req, &status)) {
     1198                tevent_req_received(req);
     1199                return status;
     1200        }
     1201
     1202        *out_data = talloc_move(mem_ctx, &state->out_data.data);
     1203        *out_length = state->out_data.length;
     1204        *out_flags = 0;
     1205        tevent_req_received(req);
     1206        return NT_STATUS_OK;
     1207}
     1208
     1209struct irpc_bh_disconnect_state {
     1210        uint8_t _dummy;
     1211};
     1212
     1213static struct tevent_req *irpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
     1214                                                struct tevent_context *ev,
     1215                                                struct dcerpc_binding_handle *h)
     1216{
     1217        struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
     1218                                     struct irpc_bh_state);
     1219        struct tevent_req *req;
     1220        struct irpc_bh_disconnect_state *state;
     1221        bool ok;
     1222
     1223        req = tevent_req_create(mem_ctx, &state,
     1224                                struct irpc_bh_disconnect_state);
     1225        if (req == NULL) {
     1226                return NULL;
     1227        }
     1228
     1229        ok = irpc_bh_is_connected(h);
     1230        if (!ok) {
     1231                tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
     1232                return tevent_req_post(req, ev);
     1233        }
     1234
     1235        hs->msg_ctx = NULL;
     1236
     1237        tevent_req_done(req);
     1238        return tevent_req_post(req, ev);
     1239}
     1240
     1241static NTSTATUS irpc_bh_disconnect_recv(struct tevent_req *req)
     1242{
     1243        NTSTATUS status;
     1244
     1245        if (tevent_req_is_nterror(req, &status)) {
     1246                tevent_req_received(req);
     1247                return status;
     1248        }
     1249
     1250        tevent_req_received(req);
     1251        return NT_STATUS_OK;
     1252}
     1253
     1254static bool irpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
     1255{
     1256        return true;
     1257}
     1258
     1259static const struct dcerpc_binding_handle_ops irpc_bh_ops = {
     1260        .name                   = "wbint",
     1261        .is_connected           = irpc_bh_is_connected,
     1262        .set_timeout            = irpc_bh_set_timeout,
     1263        .raw_call_send          = irpc_bh_raw_call_send,
     1264        .raw_call_recv          = irpc_bh_raw_call_recv,
     1265        .disconnect_send        = irpc_bh_disconnect_send,
     1266        .disconnect_recv        = irpc_bh_disconnect_recv,
     1267
     1268        .ref_alloc              = irpc_bh_ref_alloc,
     1269};
     1270
     1271/* initialise a irpc binding handle */
     1272struct dcerpc_binding_handle *irpc_binding_handle(TALLOC_CTX *mem_ctx,
     1273                                        struct messaging_context *msg_ctx,
     1274                                        struct server_id server_id,
     1275                                        const struct ndr_interface_table *table)
     1276{
     1277        struct dcerpc_binding_handle *h;
     1278        struct irpc_bh_state *hs;
     1279
     1280        h = dcerpc_binding_handle_create(mem_ctx,
     1281                                         &irpc_bh_ops,
     1282                                         NULL,
     1283                                         table,
     1284                                         &hs,
     1285                                         struct irpc_bh_state,
     1286                                         __location__);
     1287        if (h == NULL) {
     1288                return NULL;
     1289        }
     1290        hs->msg_ctx = msg_ctx;
     1291        hs->server_id = server_id;
     1292        hs->table = table;
     1293        hs->timeout = IRPC_CALL_TIMEOUT;
     1294
     1295        dcerpc_binding_handle_set_sync_ev(h, msg_ctx->event.ev);
     1296
     1297        return h;
     1298}
     1299
     1300struct dcerpc_binding_handle *irpc_binding_handle_by_name(TALLOC_CTX *mem_ctx,
     1301                                        struct messaging_context *msg_ctx,
     1302                                        const char *dest_task,
     1303                                        const struct ndr_interface_table *table)
     1304{
     1305        struct dcerpc_binding_handle *h;
     1306        struct server_id *sids;
     1307        struct server_id sid;
     1308
     1309        /* find the server task */
     1310        sids = irpc_servers_byname(msg_ctx, mem_ctx, dest_task);
     1311        if (sids == NULL) {
     1312                errno = EADDRNOTAVAIL;
     1313                return NULL;
     1314        }
     1315        if (sids[0].id == 0) {
     1316                talloc_free(sids);
     1317                errno = EADDRNOTAVAIL;
     1318                return NULL;
     1319        }
     1320        sid = sids[0];
     1321        talloc_free(sids);
     1322
     1323        h = irpc_binding_handle(mem_ctx, msg_ctx,
     1324                                sid, table);
     1325        if (h == NULL) {
     1326                return NULL;
     1327        }
     1328
     1329        return h;
     1330}
     1331
     1332void irpc_binding_handle_add_security_token(struct dcerpc_binding_handle *h,
     1333                                            struct security_token *token)
     1334{
     1335        struct irpc_bh_state *hs =
     1336                dcerpc_binding_handle_data(h,
     1337                struct irpc_bh_state);
     1338
     1339        hs->token = token;
     1340}
  • trunk/server/source4/lib/messaging/messaging.h

    r414 r745  
    2222#define _MESSAGES_H_
    2323
     24#include "librpc/gen_ndr/server_id4.h"
     25
    2426struct messaging_context;
    2527
     
    3335#define MSG_PVFS_NOTIFY         7
    3436#define MSG_NTVFS_OPLOCK_BREAK  8
     37#define MSG_DREPL_ALLOCATE_RID  9
    3538
    3639/* temporary messaging endpoints are allocated above this line */
     
    4043#define SAMBA_PARENT_TASKID     0
    4144
     45typedef void (*msg_callback_t)(struct messaging_context *msg, void *private_data,
     46                               uint32_t msg_type,
     47                               struct server_id server_id, DATA_BLOB *data);
     48
     49NTSTATUS messaging_send(struct messaging_context *msg, struct server_id server,
     50                        uint32_t msg_type, const DATA_BLOB *data);
     51NTSTATUS messaging_register(struct messaging_context *msg, void *private_data,
     52                            uint32_t msg_type,
     53                            msg_callback_t fn);
     54NTSTATUS messaging_register_tmp(struct messaging_context *msg, void *private_data,
     55                                msg_callback_t fn, uint32_t *msg_type);
     56struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
     57                                         const char *dir,
     58                                         struct server_id server_id,
     59                                         struct tevent_context *ev);
     60struct messaging_context *messaging_client_init(TALLOC_CTX *mem_ctx,
     61                                         const char *dir,
     62                                         struct tevent_context *ev);
     63NTSTATUS messaging_send_ptr(struct messaging_context *msg, struct server_id server,
     64                            uint32_t msg_type, void *ptr);
     65void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void *private_data);
     66struct server_id messaging_get_server_id(struct messaging_context *msg_ctx);
     67
    4268#endif
  • trunk/server/source4/lib/messaging/pymessaging.c

    r414 r745  
    2020*/
    2121
     22#include <Python.h>
    2223#include "includes.h"
    23 #include <Python.h>
    2424#include "scripting/python/modules.h"
    2525#include "libcli/util/pyerrors.h"
    26 #include "librpc/rpc/pyrpc.h"
    27 #include "lib/messaging/irpc.h"
     26#include "librpc/rpc/pyrpc_util.h"
     27#include "librpc/ndr/libndr.h"
    2828#include "lib/messaging/messaging.h"
    2929#include "lib/events/events.h"
     
    3131#include "param/param.h"
    3232#include "param/pyparam.h"
    33 
    34 #ifndef Py_RETURN_NONE
    35 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
    36 #endif
    37 
    38 PyAPI_DATA(PyTypeObject) messaging_Type;
    39 PyAPI_DATA(PyTypeObject) irpc_ClientConnectionType;
    40 
    41 /* FIXME: This prototype should be in py_irpc.h, or shared otherwise */
    42 extern const struct PyNdrRpcMethodDef py_ndr_irpc_methods[];
     33#include "librpc/rpc/dcerpc.h"
     34#include "librpc/gen_ndr/server_id4.h"
     35
     36void initmessaging(void);
     37
     38extern PyTypeObject messaging_Type;
    4339
    4440static bool server_id_from_py(PyObject *object, struct server_id *server_id)
     
    6662} messaging_Object;
    6763
    68 PyObject *py_messaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)
     64static PyObject *py_messaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)
    6965{
    7066        struct tevent_context *ev;
     
    8884
    8985        if (messaging_path == NULL) {
    90                 messaging_path = lp_messaging_path(ret->mem_ctx,
     86                messaging_path = lpcfg_messaging_path(ret->mem_ctx,
    9187                                                                   py_default_loadparm_context(ret->mem_ctx));
    9288        } else {
     
    10399                                            messaging_path,
    104100                                            server_id,
    105                                         py_iconv_convenience(ret->mem_ctx),
    106101                                            ev);
    107102        } else {
    108103                ret->msg_ctx = messaging_client_init(ret->mem_ctx,
    109104                                            messaging_path,
    110                                         py_iconv_convenience(ret->mem_ctx),
    111105                                            ev);
    112106        }
     
    125119        messaging_Object *iface = (messaging_Object *)self;
    126120        talloc_free(iface->msg_ctx);
    127         PyObject_Del(self);
     121        self->ob_type->tp_free(self);
    128122}
    129123
     
    139133        int length;
    140134
    141         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ois#|:send",
     135        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ois#:send",
    142136                discard_const_p(char *, kwnames), &target, &msg_type, &data.data, &length)) {
     137
    143138                return NULL;
    144139        }
     
    146141        data.length = length;
    147142
    148         if (!server_id_from_py(target, &server)) 
     143        if (!server_id_from_py(target, &server))
    149144                return NULL;
    150145
     
    177172        const char *kwnames[] = { "callback", "msg_type", NULL };
    178173       
    179         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:send",
     174        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:register",
    180175                discard_const_p(char *, kwnames), &callback, &msg_type)) {
    181176                return NULL;
     
    208203        const char *kwnames[] = { "callback", "msg_type", NULL };
    209204
    210         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:send",
     205        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:deregister",
    211206                discard_const_p(char *, kwnames), &callback, &msg_type)) {
    212207                return NULL;
     
    216211
    217212        Py_DECREF(callback);
    218 
    219         Py_RETURN_NONE;
    220 }
    221 
    222 static PyObject *py_messaging_add_name(PyObject *self, PyObject *args, PyObject *kwargs)
    223 {
    224         messaging_Object *iface = (messaging_Object *)self;
    225         NTSTATUS status;
    226         char *name;
    227         const char *kwnames[] = { "name", NULL };
    228 
    229         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|:send",
    230                 discard_const_p(char *, kwnames), &name)) {
    231                 return NULL;
    232         }
    233 
    234         status = irpc_add_name(iface->msg_ctx, name);
    235         if (NT_STATUS_IS_ERR(status)) {
    236                 PyErr_SetNTSTATUS(status);
    237                 return NULL;
    238         }
    239 
    240         Py_RETURN_NONE;
    241 }
    242 
    243 
    244 static PyObject *py_messaging_remove_name(PyObject *self, PyObject *args, PyObject *kwargs)
    245 {
    246         messaging_Object *iface = (messaging_Object *)self;
    247         char *name;
    248         const char *kwnames[] = { "name", NULL };
    249 
    250         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|:send",
    251                 discard_const_p(char *, kwnames), &name)) {
    252                 return NULL;
    253         }
    254 
    255         irpc_remove_name(iface->msg_ctx, name);
    256213
    257214        Py_RETURN_NONE;
     
    265222        { "deregister", (PyCFunction)py_messaging_deregister, METH_VARARGS|METH_KEYWORDS,
    266223                "S.deregister(callback, msg_type) -> None\nDeregister a message handler" },
    267         { "add_name", (PyCFunction)py_messaging_add_name, METH_VARARGS|METH_KEYWORDS, "S.add_name(name) -> None\nListen on another name" },
    268         { "remove_name", (PyCFunction)py_messaging_remove_name, METH_VARARGS|METH_KEYWORDS, "S.remove_name(name) -> None\nStop listening on a name" },
    269224        { NULL, NULL, 0, NULL }
    270225};
     
    288243PyTypeObject messaging_Type = {
    289244        PyObject_HEAD_INIT(NULL) 0,
    290         .tp_name = "irpc.Messaging",
     245        .tp_name = "messaging.Messaging",
    291246        .tp_basicsize = sizeof(messaging_Object),
    292247        .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
     
    300255};
    301256
    302 
    303 /*
    304   state of a irpc 'connection'
    305 */
    306 typedef struct {
    307         PyObject_HEAD
    308         const char *server_name;
    309         struct server_id *dest_ids;
    310         struct messaging_context *msg_ctx;
    311         TALLOC_CTX *mem_ctx;
    312 } irpc_ClientConnectionObject;
    313 
    314 /*
    315   setup a context for talking to a irpc server
    316      example:
    317         status = irpc.connect("smb_server");
    318 */
    319 
    320 PyObject *py_irpc_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)
    321 {
    322         struct tevent_context *ev;
    323         const char *kwnames[] = { "server", "own_id", "messaging_path", NULL };
    324         char *server;
    325         const char *messaging_path = NULL;
    326         PyObject *own_id = Py_None;
    327         irpc_ClientConnectionObject *ret;
    328 
    329         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oz:connect",
    330                 discard_const_p(char *, kwnames), &server, &own_id, &messaging_path)) {
    331                 return NULL;
    332         }
    333 
    334         ret = PyObject_New(irpc_ClientConnectionObject, &irpc_ClientConnectionType);
    335         if (ret == NULL)
    336                 return NULL;
    337 
    338         ret->mem_ctx = talloc_new(NULL);
    339 
    340         ret->server_name = server;
    341 
    342         ev = s4_event_context_init(ret->mem_ctx);
    343 
    344         if (messaging_path == NULL) {
    345                 messaging_path = lp_messaging_path(ret->mem_ctx,
    346                                                                    py_default_loadparm_context(ret->mem_ctx));
    347         } else {
    348                 messaging_path = talloc_strdup(ret->mem_ctx, messaging_path);
    349         }
    350 
    351         if (own_id != Py_None) {
    352                 struct server_id server_id;
    353 
    354                 if (!server_id_from_py(own_id, &server_id))
    355                         return NULL;
    356 
    357                 ret->msg_ctx = messaging_init(ret->mem_ctx,
    358                                             messaging_path,
    359                                             server_id,
    360                                         py_iconv_convenience(ret->mem_ctx),
    361                                             ev);
    362         } else {
    363                 ret->msg_ctx = messaging_client_init(ret->mem_ctx,
    364                                             messaging_path,
    365                                         py_iconv_convenience(ret->mem_ctx),
    366                                             ev);
    367         }
    368 
    369         if (ret->msg_ctx == NULL) {
    370                 PyErr_SetString(PyExc_RuntimeError, "irpc_connect unable to create a messaging context");
    371                 talloc_free(ret->mem_ctx);
    372                 return NULL;
    373         }
    374 
    375         ret->dest_ids = irpc_servers_byname(ret->msg_ctx, ret->mem_ctx, ret->server_name);
    376         if (ret->dest_ids == NULL || ret->dest_ids[0].id == 0) {
    377                 talloc_free(ret->mem_ctx);
    378                 PyErr_SetNTSTATUS(NT_STATUS_OBJECT_NAME_NOT_FOUND);
    379                 return NULL;
    380         } else {
    381                 return (PyObject *)ret;
    382         }
    383 }
    384 
    385 typedef struct {
    386         PyObject_HEAD
    387         struct irpc_request **reqs;
    388         int count;
    389         int current;
    390         TALLOC_CTX *mem_ctx;
    391         py_data_unpack_fn unpack_fn;
    392 } irpc_ResultObject;
    393 
    394        
    395 static PyObject *irpc_result_next(irpc_ResultObject *iterator)
    396 {
    397         NTSTATUS status;
    398 
    399         if (iterator->current >= iterator->count) {
    400                 PyErr_SetString(PyExc_StopIteration, "No more results");
    401                 return NULL;
    402         }
    403 
    404         status = irpc_call_recv(iterator->reqs[iterator->current]);
    405         iterator->current++;
    406         if (!NT_STATUS_IS_OK(status)) {
    407                 PyErr_SetNTSTATUS(status);
    408                 return NULL;
    409         }
    410 
    411         return iterator->unpack_fn(iterator->reqs[iterator->current-1]->r);
    412 }
    413 
    414 static PyObject *irpc_result_len(irpc_ResultObject *self)
    415 {
    416         return PyLong_FromLong(self->count);
    417 }
    418 
    419 static PyMethodDef irpc_result_methods[] = {
    420         { "__len__", (PyCFunction)irpc_result_len, METH_NOARGS,
    421                 "Number of elements returned"},
    422         { NULL }
    423 };
    424 
    425 static void irpc_result_dealloc(PyObject *self)
    426 {
    427         talloc_free(((irpc_ResultObject *)self)->mem_ctx);
    428         PyObject_Del(self);
    429 }
    430 
    431 PyTypeObject irpc_ResultIteratorType = {
    432         PyObject_HEAD_INIT(NULL) 0,
    433         .tp_name = "irpc.ResultIterator",
    434         .tp_basicsize = sizeof(irpc_ResultObject),
    435         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    436         .tp_iternext = (iternextfunc)irpc_result_next,
    437         .tp_iter = PyObject_SelfIter,
    438         .tp_methods = irpc_result_methods,
    439         .tp_dealloc = irpc_result_dealloc,
    440 };
    441 
    442 static PyObject *py_irpc_call(irpc_ClientConnectionObject *p, struct PyNdrRpcMethodDef *method_def, PyObject *args, PyObject *kwargs)
    443 {
    444         void *ptr;
    445         struct irpc_request **reqs;
    446         int i, count;
    447         NTSTATUS status;
    448         TALLOC_CTX *mem_ctx = talloc_new(NULL);
    449         irpc_ResultObject *ret;
    450 
    451         /* allocate the C structure */
    452         ptr = talloc_zero_size(mem_ctx, method_def->table->calls[method_def->opnum].struct_size);
    453         if (ptr == NULL) {
    454                 status = NT_STATUS_NO_MEMORY;
    455                 goto done;
    456         }
    457 
    458         /* convert the mpr object into a C structure */
    459         if (!method_def->pack_in_data(args, kwargs, ptr)) {
    460                 talloc_free(mem_ctx);
    461                 return NULL;
    462         }
    463 
    464         for (count=0;p->dest_ids[count].id;count++) /* noop */ ;
    465 
    466         /* we need to make a call per server */
    467         reqs = talloc_array(mem_ctx, struct irpc_request *, count);
    468         if (reqs == NULL) {
    469                 status = NT_STATUS_NO_MEMORY;
    470                 goto done;
    471         }
    472 
    473         /* make the actual calls */
    474         for (i=0;i<count;i++) {
    475                 reqs[i] = irpc_call_send(p->msg_ctx, p->dest_ids[i],
    476                                          method_def->table, method_def->opnum, ptr, ptr);
    477                 if (reqs[i] == NULL) {
    478                         status = NT_STATUS_NO_MEMORY;
    479                         goto done;
    480                 }
    481                 talloc_steal(reqs, reqs[i]);
    482         }
    483 
    484         ret = PyObject_New(irpc_ResultObject, &irpc_ResultIteratorType);
    485         ret->mem_ctx = mem_ctx;
    486         ret->reqs = reqs;
    487         ret->count = count;
    488         ret->current = 0;
    489         ret->unpack_fn = method_def->unpack_out_data;
    490 
    491         return (PyObject *)ret;
    492 done:
    493         talloc_free(mem_ctx);
    494         PyErr_SetNTSTATUS(status);
    495         return NULL;
    496 }
    497 
    498 static PyObject *py_irpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs)
    499 {       
    500         irpc_ClientConnectionObject *iface = (irpc_ClientConnectionObject *)self;
    501         struct PyNdrRpcMethodDef *md = wrapped;
    502 
    503         return py_irpc_call(iface, md, args, kwargs);
    504 }
    505 
    506 static void py_irpc_dealloc(PyObject *self)
    507 {
    508         irpc_ClientConnectionObject *iface = (irpc_ClientConnectionObject *)self;
    509         talloc_free(iface->mem_ctx);
    510         PyObject_Del(self);
    511 }
    512 
    513 PyTypeObject irpc_ClientConnectionType = {
    514         PyObject_HEAD_INIT(NULL) 0,
    515         .tp_name = "irpc.ClientConnection",
    516         .tp_basicsize = sizeof(irpc_ClientConnectionObject),
    517         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    518         .tp_new = py_irpc_connect,
    519         .tp_dealloc = py_irpc_dealloc,
    520         .tp_doc = "ClientConnection(server, own_id=None, messaging_path=None)\n" \
    521                   "Create a new IRPC client connection to communicate with the servers in the specified path.\n" \
    522                   "If no path is specified, the default path from smb.conf will be used."
    523 };
    524 
    525 static bool irpc_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpcMethodDef *mds)
    526 {
    527         int i;
    528         for (i = 0; mds[i].name; i++) {
    529                 PyObject *ret;
    530                 struct wrapperbase *wb = calloc(sizeof(struct wrapperbase), 1);
    531 
    532                 wb->name = discard_const_p(char, mds[i].name);
    533                 wb->flags = PyWrapperFlag_KEYWORDS;
    534                 wb->wrapper = (wrapperfunc)py_irpc_call_wrapper;
    535                 wb->doc = discard_const_p(char, mds[i].doc);
    536                
    537                 ret = PyDescr_NewWrapper(ifacetype, wb, discard_const_p(void, &mds[i]));
    538 
    539                 PyDict_SetItemString(ifacetype->tp_dict, mds[i].name,
    540                                      (PyObject *)ret);
    541         }
    542 
    543         return true;
    544 }
    545 
    546257void initmessaging(void)
    547258{
    548259        PyObject *mod;
    549         PyObject *dep_irpc;
    550 
    551         dep_irpc = PyImport_ImportModule("samba.dcerpc.irpc");
    552         if (dep_irpc == NULL)
    553                 return;
    554 
    555         if (PyType_Ready(&irpc_ClientConnectionType) < 0)
    556                 return;
    557260
    558261        if (PyType_Ready(&messaging_Type) < 0)
    559                 return;
    560 
    561         if (PyType_Ready(&irpc_ResultIteratorType) < 0)
    562                 return;
    563 
    564         if (!irpc_AddNdrRpcMethods(&irpc_ClientConnectionType, py_ndr_irpc_methods))
    565262                return;
    566263
     
    569266                return;
    570267
    571         Py_INCREF((PyObject *)&irpc_ClientConnectionType);
    572         PyModule_AddObject(mod, "ClientConnection", (PyObject *)&irpc_ClientConnectionType);
    573 
    574268        Py_INCREF((PyObject *)&messaging_Type);
    575269        PyModule_AddObject(mod, "Messaging", (PyObject *)&messaging_Type);
  • trunk/server/source4/lib/messaging/tests/irpc.c

    r414 r745  
    2424#include "lib/messaging/irpc.h"
    2525#include "librpc/gen_ndr/ndr_echo.h"
     26#include "librpc/gen_ndr/ndr_echo_c.h"
    2627#include "torture/torture.h"
    2728#include "cluster/cluster.h"
     
    5859{
    5960        struct irpc_message *irpc = talloc_get_type(private_data, struct irpc_message);
    60         struct echo_EchoData *r = irpc->data;
    61         r->out.out_data = talloc_memdup(r, r->in.in_data, r->in.len);
     61        struct echo_EchoData *r = (struct echo_EchoData *)irpc->data;
     62        r->out.out_data = (uint8_t *)talloc_memdup(r, r->in.in_data, r->in.len);
    6263        if (r->out.out_data == NULL) {
    6364                irpc_send_reply(irpc, NT_STATUS_NO_MEMORY);
     
    8990        const struct irpc_test_data *data = (const struct irpc_test_data *)_data;
    9091        uint32_t value = *(const uint32_t *)_value;
     92        struct dcerpc_binding_handle *irpc_handle;
     93
     94        irpc_handle = irpc_binding_handle(test, data->msg_ctx1,
     95                                          cluster_id(0, MSG_ID2),
     96                                          &ndr_table_rpcecho);
     97        torture_assert(test, irpc_handle, "no memory");
    9198
    9299        /* make the call */
     
    94101
    95102        test_debug = true;
    96         status = IRPC_CALL(data->msg_ctx1, cluster_id(0, MSG_ID2),
    97                            rpcecho, ECHO_ADDONE, &r, test);
     103        status = dcerpc_echo_AddOne_r(irpc_handle, test, &r);
    98104        test_debug = false;
    99105        torture_assert_ntstatus_ok(test, status, "AddOne failed");
     
    118124        const struct irpc_test_data *data = (const struct irpc_test_data *)tcase_data;
    119125        TALLOC_CTX *mem_ctx = tctx;
     126        struct dcerpc_binding_handle *irpc_handle;
     127
     128        irpc_handle = irpc_binding_handle(mem_ctx, data->msg_ctx1,
     129                                          cluster_id(0, MSG_ID2),
     130                                          &ndr_table_rpcecho);
     131        torture_assert(tctx, irpc_handle, "no memory");
    120132
    121133        /* make the call */
     
    123135        r.in.len = strlen((char *)r.in.in_data);
    124136
    125         status = IRPC_CALL(data->msg_ctx1, cluster_id(0, MSG_ID2),
    126                            rpcecho, ECHO_ECHODATA, &r,
    127                            mem_ctx);
     137        status = dcerpc_echo_EchoData_r(irpc_handle, mem_ctx, &r);
    128138        torture_assert_ntstatus_ok(tctx, status, "EchoData failed");
    129139
     
    142152}
    143153
    144 
    145 static void irpc_callback(struct irpc_request *irpc)
    146 {
    147         struct echo_AddOne *r = (struct echo_AddOne *)irpc->r;
    148         int *pong_count = (int *)irpc->async.private_data;
    149         NTSTATUS status = irpc_call_recv(irpc);
     154struct irpc_callback_state {
     155        struct echo_AddOne r;
     156        int *pong_count;
     157};
     158
     159static void irpc_callback(struct tevent_req *subreq)
     160{
     161        struct irpc_callback_state *s =
     162                tevent_req_callback_data(subreq,
     163                struct irpc_callback_state);
     164        NTSTATUS status;
     165
     166        status = dcerpc_echo_AddOne_r_recv(subreq, s);
     167        TALLOC_FREE(subreq);
    150168        if (!NT_STATUS_IS_OK(status)) {
    151169                printf("irpc call failed - %s\n", nt_errstr(status));
    152170        }
    153         if (*r->out.out_data != r->in.in_data + 1) {
     171        if (*s->r.out.out_data != s->r.in.in_data + 1) {
    154172                printf("AddOne wrong answer - %u + 1 = %u should be %u\n",
    155                        r->in.in_data, *r->out.out_data, r->in.in_data+1);
    156         }
    157         (*pong_count)++;
     173                       s->r.in.in_data, *s->r.out.out_data, s->r.in.in_data+1);
     174        }
     175        (*s->pong_count)++;
    158176}
    159177
     
    169187        const struct irpc_test_data *data = (const struct irpc_test_data *)tcase_data;
    170188        struct timeval tv;
    171         struct echo_AddOne r;
    172189        TALLOC_CTX *mem_ctx = tctx;
    173190        int timelimit = torture_setting_int(tctx, "timelimit", 10);
     191        struct dcerpc_binding_handle *irpc_handle;
     192
     193        irpc_handle = irpc_binding_handle(mem_ctx, data->msg_ctx1,
     194                                          cluster_id(0, MSG_ID2),
     195                                          &ndr_table_rpcecho);
     196        torture_assert(tctx, irpc_handle, "no memory");
    174197
    175198        tv = timeval_current();
    176 
    177         r.in.in_data = 0;
    178199
    179200        torture_comment(tctx, "Sending echo for %d seconds\n", timelimit);
    180201        while (timeval_elapsed(&tv) < timelimit) {
    181                 struct irpc_request *irpc;
    182 
    183                 irpc = IRPC_CALL_SEND(data->msg_ctx1, cluster_id(0, MSG_ID2),
    184                                       rpcecho, ECHO_ADDONE,
    185                                       &r, mem_ctx);
    186                 torture_assert(tctx, irpc != NULL, "AddOne send failed");
    187 
    188                 irpc->async.fn = irpc_callback;
    189                 irpc->async.private_data = &pong_count;
     202                struct tevent_req *subreq;
     203                struct irpc_callback_state *s;
     204
     205                s = talloc_zero(mem_ctx, struct irpc_callback_state);
     206                torture_assert(tctx, s != NULL, "no mem");
     207
     208                s->pong_count = &pong_count;
     209
     210                subreq = dcerpc_echo_AddOne_r_send(mem_ctx,
     211                                                   tctx->ev,
     212                                                   irpc_handle,
     213                                                   &s->r);
     214                torture_assert(tctx, subreq != NULL, "AddOne send failed");
     215
     216                tevent_req_set_callback(subreq, irpc_callback, s);
    190217
    191218                ping_count++;
     
    216243        *_data = data = talloc(tctx, struct irpc_test_data);
    217244
    218         lp_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
     245        lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
    219246
    220247        data->ev = tctx->ev;
    221248        torture_assert(tctx, data->msg_ctx1 =
    222249                       messaging_init(tctx,
    223                                       lp_messaging_path(tctx, tctx->lp_ctx),
     250                                      lpcfg_messaging_path(tctx, tctx->lp_ctx),
    224251                                      cluster_id(0, MSG_ID1),
    225                                       lp_iconv_convenience(tctx->lp_ctx),
    226252                                      data->ev),
    227253                       "Failed to init first messaging context");
     
    229255        torture_assert(tctx, data->msg_ctx2 =
    230256                       messaging_init(tctx,
    231                                       lp_messaging_path(tctx, tctx->lp_ctx),
     257                                      lpcfg_messaging_path(tctx, tctx->lp_ctx),
    232258                                      cluster_id(0, MSG_ID2),
    233                                       lp_iconv_convenience(tctx->lp_ctx),
    234259                                      data->ev),
    235260                       "Failed to init second messaging context");
     
    247272struct torture_suite *torture_local_irpc(TALLOC_CTX *mem_ctx)
    248273{
    249         struct torture_suite *suite = torture_suite_create(mem_ctx, "IRPC");
     274        struct torture_suite *suite = torture_suite_create(mem_ctx, "irpc");
    250275        struct torture_tcase *tcase = torture_suite_add_tcase(suite, "irpc");
    251276        int i;
  • trunk/server/source4/lib/messaging/tests/messaging.c

    r414 r745  
    6868        uint32_t msg_ping, msg_exit;
    6969
    70         lp_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
     70        lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
    7171
    7272        ev = tctx->ev;
    7373
    7474        msg_server_ctx = messaging_init(tctx,
    75                                         lp_messaging_path(tctx, tctx->lp_ctx),
    76                                         cluster_id(0, 1),
    77                                         lp_iconv_convenience(tctx->lp_ctx),
     75                                        lpcfg_messaging_path(tctx, tctx->lp_ctx), cluster_id(0, 1),
    7876                                        ev);
    7977       
     
    8482
    8583        msg_client_ctx = messaging_init(tctx,
    86                                         lp_messaging_path(tctx, tctx->lp_ctx),
     84                                        lpcfg_messaging_path(tctx, tctx->lp_ctx),
    8785                                        cluster_id(0, 2),
    88                                         lp_iconv_convenience(tctx->lp_ctx),
    8986                                        ev);
    9087
     
    140137struct torture_suite *torture_local_messaging(TALLOC_CTX *mem_ctx)
    141138{
    142         struct torture_suite *s = torture_suite_create(mem_ctx, "MESSAGING");
     139        struct torture_suite *s = torture_suite_create(mem_ctx, "messaging");
    143140        torture_suite_add_simple_test(s, "ping_speed", test_ping_speed);
    144141        return s;
  • trunk/server/source4/lib/registry/dir.c

    r414 r745  
    4141
    4242        path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
     43        W_ERROR_HAVE_NO_MEMORY(path);
    4344        ret = mkdir(path, 0700);
    4445        if (ret == 0) {
    4546                struct dir_key *key = talloc(mem_ctx, struct dir_key);
     47                W_ERROR_HAVE_NO_MEMORY(key);
    4648                key->key.ops = &reg_backend_dir;
    4749                key->path = talloc_steal(key, path);
     
    7779
    7880                path = talloc_asprintf(name, "%s/%s", name, e->d_name);
    79                 if (!path)
    80                         return WERR_NOMEM;
     81                W_ERROR_HAVE_NO_MEMORY(path);
    8182
    8283                stat(path, &stbuf);
     
    109110}
    110111
    111 static WERROR reg_dir_del_key(const struct hive_key *k, const char *name)
     112static WERROR reg_dir_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *k,
     113                              const char *name)
    112114{
    113115        struct dir_key *dk = talloc_get_type(k, struct dir_key);
    114         char *child = talloc_asprintf(NULL, "%s/%s", dk->path, name);
     116        char *child;
    115117        WERROR ret;
     118
     119        child = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
     120        W_ERROR_HAVE_NO_MEMORY(child);
    116121
    117122        ret = reg_dir_delete_recursive(child);
     
    137142
    138143        fullpath = talloc_asprintf(mem_ctx, "%s/%s", p->path, name);
     144        W_ERROR_HAVE_NO_MEMORY(fullpath);
    139145
    140146        d = opendir(fullpath);
     
    142148                DEBUG(3,("Unable to open '%s': %s\n", fullpath,
    143149                        strerror(errno)));
     150                talloc_free(fullpath);
    144151                return WERR_BADFILE;
    145152        }
     
    160167        struct dirent *e;
    161168        const struct dir_key *dk = talloc_get_type(k, struct dir_key);
    162         int i = 0;
     169        unsigned int i = 0;
    163170        DIR *d;
    164171
     
    174181
    175182                        /* Check if file is a directory */
    176                         asprintf(&thispath, "%s/%s", dk->path, e->d_name);
     183                        thispath = talloc_asprintf(mem_ctx, "%s/%s", dk->path,
     184                                                   e->d_name);
     185                        W_ERROR_HAVE_NO_MEMORY(thispath);
    177186                        stat(thispath, &stbuf);
    178187
    179188                        if (!S_ISDIR(stbuf.st_mode)) {
    180                                 SAFE_FREE(thispath);
     189                                talloc_free(thispath);
    181190                                continue;
    182191                        }
     
    185194                                struct stat st;
    186195                                *name = talloc_strdup(mem_ctx, e->d_name);
     196                                W_ERROR_HAVE_NO_MEMORY(*name);
    187197                                *classname = NULL;
    188198                                stat(thispath, &st);
    189199                                unix_to_nt_time(last_mod_time, st.st_mtime);
    190                                 SAFE_FREE(thispath);
     200                                talloc_free(thispath);
    191201                                closedir(d);
    192202                                return WERR_OK;
     
    194204                        i++;
    195205
    196                         SAFE_FREE(thispath);
     206                        talloc_free(thispath);
    197207                }
    198208        }
     
    212222
    213223        dk = talloc(parent_ctx, struct dir_key);
     224        W_ERROR_HAVE_NO_MEMORY(dk);
    214225        dk->key.ops = &reg_backend_dir;
    215226        dk->path = talloc_strdup(dk, location);
     
    271282                        char *path = talloc_asprintf(ctx, "%s/%s",
    272283                                                     dk->path, e->d_name);
     284                        W_ERROR_HAVE_NO_MEMORY(path);
    273285
    274286                        if (stat(path, &st) < 0) {
    275287                                DEBUG(0, ("Error statting %s: %s\n", path,
    276288                                        strerror(errno)));
     289                                talloc_free(path);
    277290                                continue;
    278291                        }
     
    309322{
    310323        const struct dir_key *dk = talloc_get_type(key, struct dir_key);
    311         char *path = talloc_asprintf(dk, "%s/%s", dk->path, name);
    312 
    313         if (!file_save(path, data.data, data.length))
     324        char *path;
     325        bool ret;
     326
     327        path = talloc_asprintf(dk, "%s/%s", dk->path, name);
     328        W_ERROR_HAVE_NO_MEMORY(path);
     329
     330        ret = file_save(path, data.data, data.length);
     331
     332        talloc_free(path);
     333
     334        if (!ret) {
    314335                return WERR_GENERAL_FAILURE;
     336        }
    315337
    316338        /* FIXME: Type */
     
    324346{
    325347        const struct dir_key *dk = talloc_get_type(key, struct dir_key);
    326         char *path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
     348        char *path;
    327349        size_t size;
    328350        char *contents;
    329351
     352        path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
     353        W_ERROR_HAVE_NO_MEMORY(path);
     354
    330355        contents = file_load(path, &size, 0, mem_ctx);
     356
    331357        talloc_free(path);
     358
    332359        if (contents == NULL)
    333360                return WERR_BADFILE;
     
    343370
    344371static WERROR reg_dir_enum_value(TALLOC_CTX *mem_ctx,
    345                                  struct hive_key *key, int idx,
     372                                 struct hive_key *key, uint32_t idx,
    346373                                 const char **name,
    347374                                 uint32_t *type, DATA_BLOB *data)
     
    350377        DIR *d;
    351378        struct dirent *e;
    352         int i;
     379        unsigned int i;
    353380
    354381        d = opendir(dk->path);
     
    365392
    366393                if (i == idx) {
    367                         if (name != NULL)
     394                        if (name != NULL) {
    368395                                *name = talloc_strdup(mem_ctx, e->d_name);
     396                                W_ERROR_HAVE_NO_MEMORY(*name);
     397                        }
    369398                        W_ERROR_NOT_OK_RETURN(reg_dir_get_value(mem_ctx, key,
    370399                                                                *name, type,
     
    381410
    382411
    383 static WERROR reg_dir_del_value (struct hive_key *key, const char *name)
     412static WERROR reg_dir_del_value(TALLOC_CTX *mem_ctx,
     413                                struct hive_key *key, const char *name)
    384414{
    385415        const struct dir_key *dk = talloc_get_type(key, struct dir_key);
    386         char *path = talloc_asprintf(key, "%s/%s", dk->path, name);
    387         if (unlink(path) < 0) {
    388                 talloc_free(path);
     416        char *path;
     417        int ret;
     418
     419        path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
     420        W_ERROR_HAVE_NO_MEMORY(path);
     421
     422        ret = unlink(path);
     423
     424        talloc_free(path);
     425
     426        if (ret < 0) {
    389427                if (errno == ENOENT)
    390428                        return WERR_BADFILE;
    391429                return WERR_GENERAL_FAILURE;
    392430        }
    393         talloc_free(path);
    394431
    395432        return WERR_OK;
  • trunk/server/source4/lib/registry/hive.c

    r414 r745  
    5555        if (!strncmp(peek, "regf", 4)) {
    5656                close(fd);
    57                 return reg_open_regf_file(parent_ctx, location, lp_iconv_convenience(lp_ctx), root);
     57                return reg_open_regf_file(parent_ctx, location, root);
    5858        } else if (!strncmp(peek, "TDB file", 8)) {
    5959                close(fd);
     
    9292}
    9393
    94 _PUBLIC_ WERROR hive_key_del(const struct hive_key *key, const char *name)
     94_PUBLIC_ WERROR hive_key_del(TALLOC_CTX *mem_ctx, const struct hive_key *key,
     95                             const char *name)
    9596{
    96         return key->ops->del_key(key, name);
     97        return key->ops->del_key(mem_ctx, key, name);
    9798}
    9899
     
    164165}
    165166
    166 WERROR hive_key_del_value(struct hive_key *key, const char *name)
     167WERROR hive_key_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key,
     168                          const char *name)
    167169{
    168170        if (key->ops->delete_value == NULL)
    169171                return WERR_NOT_SUPPORTED;
    170172
    171         return key->ops->delete_value(key, name);
     173        return key->ops->delete_value(mem_ctx, key, name);
    172174}
    173175
  • trunk/server/source4/lib/registry/interface.c

    r414 r745  
    4545_PUBLIC_ const char *reg_get_predef_name(uint32_t hkey)
    4646{
    47         int i;
     47        unsigned int i;
    4848        for (i = 0; reg_predefined_keys[i].name; i++) {
    4949                if (reg_predefined_keys[i].handle == hkey)
     
    5959                                               struct registry_key **key)
    6060{
    61         int i;
     61        unsigned int i;
    6262
    6363        for (i = 0; reg_predefined_keys[i].name; i++) {
     
    151151_PUBLIC_ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx,
    152152                                            const struct registry_key *key,
    153                                             int idx, const char **name,
     153                                            uint32_t idx, const char **name,
    154154                                            const char **keyclass,
    155155                                            NTTIME *last_changed_time)
     
    186186 * Delete a key.
    187187 */
    188 _PUBLIC_ WERROR reg_key_del(struct registry_key *parent, const char *name)
     188_PUBLIC_ WERROR reg_key_del(TALLOC_CTX *mem_ctx, struct registry_key *parent,
     189                            const char *name)
    189190{
    190191        if (parent == NULL)
     
    194195                return WERR_NOT_SUPPORTED;
    195196
    196         return parent->context->ops->delete_key(parent, name);
     197        return parent->context->ops->delete_key(mem_ctx, parent, name);
    197198}
    198199
     
    202203_PUBLIC_ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx,
    203204                                 struct registry_key *parent,
    204                                  const char *name, const char *key_class,
     205                                 const char *path, const char *key_class,
    205206                                 struct security_descriptor *desc,
    206207                                 struct registry_key **newkey)
     
    215216        }
    216217
    217         return parent->context->ops->create_key(mem_ctx, parent, name,
     218        return parent->context->ops->create_key(mem_ctx, parent, path,
    218219                                                key_class, desc, newkey);
    219220}
     
    258259 * Delete a value.
    259260 */
    260 _PUBLIC_ WERROR reg_del_value(struct registry_key *key, const char *valname)
     261_PUBLIC_ WERROR reg_del_value(TALLOC_CTX *mem_ctx, struct registry_key *key,
     262                              const char *valname)
    261263{
    262264        if (key == NULL)
     
    266268                return WERR_NOT_SUPPORTED;
    267269
    268         return key->context->ops->delete_value(key, valname);
     270        return key->context->ops->delete_value(mem_ctx, key, valname);
    269271}
    270272
  • trunk/server/source4/lib/registry/ldb.c

    r414 r745  
    33   Registry interface
    44   Copyright (C) 2004-2007, Jelmer Vernooij, jelmer@samba.org
    5    Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de
     5   Copyright (C) 2008-2010, Matthias Dieter Wallnöfer, mdw@samba.org
    66
    77   This program is free software; you can redistribute it and/or modify
     
    2121#include "includes.h"
    2222#include "registry.h"
    23 #include "lib/ldb/include/ldb.h"
    24 #include "lib/ldb/include/ldb_errors.h"
     23#include <ldb.h>
     24#include <ldb_errors.h>
    2525#include "ldb_wrap.h"
    2626#include "librpc/gen_ndr/winreg.h"
     
    3535        struct ldb_dn *dn;
    3636        struct ldb_message **subkeys, **values;
    37         int subkey_count, value_count;
     37        unsigned int subkey_count, value_count;
     38        const char *classname;
    3839};
    3940
    40 static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, 
     41static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx,
    4142                                 struct ldb_message *msg,
    4243                                 const char **name, uint32_t *type,
     
    4647        uint32_t value_type;
    4748
    48         if (name != NULL)
     49        if (name != NULL) {
    4950                *name = talloc_strdup(mem_ctx,
    5051                                      ldb_msg_find_attr_as_string(msg, "value",
    51                                       NULL));
     52                                      ""));
     53        }
    5254
    5355        value_type = ldb_msg_find_attr_as_uint(msg, "type", 0);
    54         *type = value_type; 
     56        *type = value_type;
    5557
    5658        val = ldb_msg_find_ldb_val(msg, "data");
     
    6062        case REG_SZ:
    6163        case REG_EXPAND_SZ:
    62                 if (val != NULL)
     64                if (val != NULL) {
     65                        /* The data should be provided as UTF16 string */
    6366                        convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16,
    64                                                      val->data, val->length,
    65                                                      (void **)&data->data, &data->length, false);
    66                 else {
     67                                              val->data, val->length,
     68                                              (void **)&data->data, &data->length, false);
     69                } else {
    6770                        data->data = NULL;
    6871                        data->length = 0;
     
    7073                break;
    7174
    72         case REG_BINARY:
    73                 if (val != NULL)
    74                         *data = data_blob_talloc(mem_ctx, val->data, val->length);
    75                 else {
     75        case REG_DWORD:
     76        case REG_DWORD_BIG_ENDIAN:
     77                if (val != NULL) {
     78                        /* The data is a plain DWORD */
     79                        uint32_t tmp = strtoul((char *)val->data, NULL, 0);
     80                        data->data = talloc_size(mem_ctx, sizeof(uint32_t));
     81                        if (data->data != NULL) {
     82                                SIVAL(data->data, 0, tmp);
     83                        }
     84                        data->length = sizeof(uint32_t);
     85                } else {
    7686                        data->data = NULL;
    7787                        data->length = 0;
     
    7989                break;
    8090
    81         case REG_DWORD: {
    82                 uint32_t tmp = strtoul((char *)val->data, NULL, 0);
    83                 *data = data_blob_talloc(mem_ctx, &tmp, 4);
     91        case REG_QWORD:
     92                if (val != NULL) {
     93                        /* The data is a plain QWORD */
     94                        uint64_t tmp = strtoull((char *)val->data, NULL, 0);
     95                        data->data = talloc_size(mem_ctx, sizeof(uint64_t));
     96                        if (data->data != NULL) {
     97                                SBVAL(data->data, 0, tmp);
     98                        }
     99                        data->length = sizeof(uint64_t);
     100                } else {
     101                        data->data = NULL;
     102                        data->length = 0;
    84103                }
    85104                break;
    86105
     106        case REG_BINARY:
    87107        default:
    88                 *data = data_blob_talloc(mem_ctx, val->data, val->length);
     108                if (val != NULL) {
     109                        data->data = talloc_memdup(mem_ctx, val->data,
     110                                                   val->length);
     111                        data->length = val->length;
     112                } else {
     113                        data->data = NULL;
     114                        data->length = 0;
     115                }
    89116                break;
    90117        }
     
    96123                                              uint32_t type, DATA_BLOB data)
    97124{
    98         struct ldb_val val;
    99         struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message);
    100         char *type_s;
    101 
    102         ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name));
     125        struct ldb_message *msg;
     126        char *name_dup, *type_str;
     127        int ret;
     128
     129        msg = talloc_zero(mem_ctx, struct ldb_message);
     130        if (msg == NULL) {
     131                return NULL;
     132        }
     133
     134        name_dup = talloc_strdup(msg, name);
     135        if (name_dup == NULL) {
     136                talloc_free(msg);
     137                return NULL;
     138        }
     139
     140        ret = ldb_msg_add_string(msg, "value", name_dup);
     141        if (ret != LDB_SUCCESS) {
     142                talloc_free(msg);
     143                return NULL;
     144        }
    103145
    104146        switch (type) {
    105147        case REG_SZ:
    106148        case REG_EXPAND_SZ:
    107                 if (data.data[0] != '\0') {
    108                         convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8,
    109                                                    (void *)data.data,
    110                                                    data.length,
    111                                                    (void **)&val.data, &val.length, false);
    112                         ldb_msg_add_value(msg, "data", &val, NULL);
     149                if ((data.length > 0) && (data.data != NULL)) {
     150                        struct ldb_val *val;
     151                        bool ret2 = false;
     152
     153                        val = talloc_zero(msg, struct ldb_val);
     154                        if (val == NULL) {
     155                                talloc_free(msg);
     156                                return NULL;
     157                        }
     158
     159                        /* The data is provided as UTF16 string */
     160                        ret2 = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8,
     161                                                     (void *)data.data, data.length,
     162                                                     (void **)&val->data, &val->length,
     163                                                     false);
     164                        if (ret2) {
     165                                ret = ldb_msg_add_value(msg, "data", val, NULL);
     166                        } else {
     167                                /* workaround for non-standard data */
     168                                ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
     169                        }
    113170                } else {
    114                         ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
     171                        ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
    115172                }
    116173                break;
    117174
     175        case REG_DWORD:
     176        case REG_DWORD_BIG_ENDIAN:
     177                if ((data.length > 0) && (data.data != NULL)) {
     178                        if (data.length == sizeof(uint32_t)) {
     179                                char *conv_str;
     180
     181                                conv_str = talloc_asprintf(msg, "0x%8.8x",
     182                                                           IVAL(data.data, 0));
     183                                if (conv_str == NULL) {
     184                                        talloc_free(msg);
     185                                        return NULL;
     186                                }
     187                                ret = ldb_msg_add_string(msg, "data", conv_str);
     188                        } else {
     189                                /* workaround for non-standard data */
     190                                talloc_free(msg);
     191                                return NULL;
     192                        }
     193                } else {
     194                        ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
     195                }
     196                break;
     197
     198        case REG_QWORD:
     199                if ((data.length > 0) && (data.data != NULL)) {
     200                        if (data.length == sizeof(uint64_t)) {
     201                                char *conv_str;
     202
     203                                conv_str = talloc_asprintf(msg, "0x%16.16llx",
     204                                                           (unsigned long long)BVAL(data.data, 0));
     205                                if (conv_str == NULL) {
     206                                        talloc_free(msg);
     207                                        return NULL;
     208                                }
     209                                ret = ldb_msg_add_string(msg, "data", conv_str);
     210                        } else {
     211                                /* workaround for non-standard data */
     212                                talloc_free(msg);
     213                                return NULL;
     214
     215                        }
     216                } else {
     217                        ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
     218                }
     219                break;
     220
    118221        case REG_BINARY:
    119                 if (data.length > 0)
    120                         ldb_msg_add_value(msg, "data", &data, NULL);
    121                 else
    122                         ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
     222        default:
     223                if ((data.length > 0) && (data.data != NULL)) {
     224                        ret = ldb_msg_add_value(msg, "data", &data, NULL);
     225                } else {
     226                        ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
     227                }
    123228                break;
    124 
    125         case REG_DWORD:
    126                 ldb_msg_add_string(msg, "data",
    127                                    talloc_asprintf(mem_ctx, "0x%x",
    128                                                    IVAL(data.data, 0)));
    129                 break;
    130         default:
    131                 ldb_msg_add_value(msg, "data", &data, NULL);
    132         }
    133 
    134 
    135         type_s = talloc_asprintf(mem_ctx, "%u", type);
    136         ldb_msg_add_string(msg, "type", type_s);
     229        }
     230
     231        if (ret != LDB_SUCCESS) {
     232                talloc_free(msg);
     233                return NULL;
     234        }
     235
     236        type_str = talloc_asprintf(mem_ctx, "%u", type);
     237        if (type_str == NULL) {
     238                talloc_free(msg);
     239                return NULL;
     240        }
     241
     242        ret = ldb_msg_add_string(msg, "type", type_str);
     243        if (ret != LDB_SUCCESS) {
     244                talloc_free(msg);
     245                return NULL;
     246        }
    137247
    138248        return msg;
     
    167277                                      const char *path, const char *add)
    168278{
    169         TALLOC_CTX *local_ctx;
    170279        struct ldb_dn *ret;
    171         char *mypath = talloc_strdup(mem_ctx, path);
     280        char *mypath;
    172281        char *begin;
    173282        struct ldb_key_data *kd = talloc_get_type(from, struct ldb_key_data);
    174283        struct ldb_context *ldb = kd->ldb;
    175284
    176         local_ctx = talloc_new(mem_ctx);
    177 
    178         if (add) {
    179                 ret = ldb_dn_new(mem_ctx, ldb, add);
    180         } else {
    181                 ret = ldb_dn_new(mem_ctx, ldb, NULL);
    182         }
     285        mypath = talloc_strdup(mem_ctx, path);
     286        if (mypath == NULL) {
     287                return NULL;
     288        }
     289
     290        ret = ldb_dn_new(mem_ctx, ldb, add);
    183291        if (!ldb_dn_validate(ret)) {
    184292                talloc_free(ret);
    185                 talloc_free(local_ctx);
    186293                return NULL;
    187294        }
    188295
    189         while (mypath) {
    190                 char *keyname;
    191 
    192                 begin = strrchr(mypath, '\\');
    193 
    194                 if (begin) keyname = begin + 1;
    195                 else keyname = mypath;
    196 
    197                 if(strlen(keyname)) {
    198                         if (!ldb_dn_add_base_fmt(ret, "key=%s",
    199                                                  reg_ldb_escape(local_ctx,
    200                                                                 keyname)))
    201                         {
    202                                 talloc_free(local_ctx);
    203                                 return NULL;
    204                         }
    205                 }
    206 
    207                 if(begin) {
     296        if (!ldb_dn_add_base(ret, kd->dn)) {
     297                talloc_free(ret);
     298                return NULL;
     299        }
     300
     301        while (mypath[0] != '\0') {
     302                begin = strchr(mypath, '\\');
     303                if (begin != NULL) {
    208304                        *begin = '\0';
     305                }
     306
     307                if (!ldb_dn_add_child_fmt(ret, "key=%s",
     308                                          reg_ldb_escape(mem_ctx, mypath))) {
     309                        talloc_free(ret);
     310                        return NULL;
     311                }
     312
     313                if (begin != NULL) {
     314                        mypath = begin + 1;
    209315                } else {
    210316                        break;
    211317                }
    212318        }
    213 
    214         ldb_dn_add_base(ret, kd->dn);
    215 
    216         talloc_free(local_ctx);
    217319
    218320        return ret;
     
    225327        int ret;
    226328
    227         ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL, NULL, "(key=*)");
    228 
     329        ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL,
     330                         NULL, "(key=*)");
    229331        if (ret != LDB_SUCCESS) {
    230332                DEBUG(0, ("Error getting subkeys for '%s': %s\n",
     
    248350        ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL,
    249351                         NULL, "(value=*)");
    250 
    251352        if (ret != LDB_SUCCESS) {
    252353                DEBUG(0, ("Error getting values for '%s': %s\n",
     
    269370                                   NTTIME *last_mod_time)
    270371{
    271         struct ldb_message_element *el;
    272372        struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
    273        
     373
    274374        /* Initialization */
    275375        if (name != NULL)
    276376                *name = NULL;
    277377        if (classname != NULL)
    278                 *classname = NULL; /* TODO: Store properly */
     378                *classname = NULL;
    279379        if (last_mod_time != NULL)
    280380                *last_mod_time = 0; /* TODO: we need to add this to the
     
    289389                return WERR_NO_MORE_ITEMS;
    290390
    291         el = ldb_msg_find_element(kd->subkeys[idx], "key");
    292         SMB_ASSERT(el != NULL);
    293         SMB_ASSERT(el->num_values != 0);
    294 
    295391        if (name != NULL)
    296                 *name = talloc_strdup(mem_ctx, (char *)el->values[0].data);
    297 
    298         return WERR_OK;
    299 }
    300 
    301 static WERROR ldb_get_default_value(TALLOC_CTX *mem_ctx, struct hive_key *k,
    302                                   const char **name, uint32_t *data_type,
    303                                    DATA_BLOB *data)
     392                *name = talloc_strdup(mem_ctx,
     393                                      ldb_msg_find_attr_as_string(kd->subkeys[idx], "key", NULL));
     394        if (classname != NULL)
     395                *classname = talloc_strdup(mem_ctx,
     396                                           ldb_msg_find_attr_as_string(kd->subkeys[idx], "classname", NULL));
     397
     398        return WERR_OK;
     399}
     400
     401static WERROR ldb_get_default_value(TALLOC_CTX *mem_ctx,
     402                                    const struct hive_key *k,
     403                                    const char **name, uint32_t *data_type,
     404                                    DATA_BLOB *data)
    304405{
    305406        struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
     
    309410        int ret;
    310411
    311         ret = ldb_search(c, mem_ctx, &res, kd->dn, LDB_SCOPE_BASE, attrs, "%s", "");
     412        ret = ldb_search(c, mem_ctx, &res, kd->dn, LDB_SCOPE_BASE, attrs, "(dn=*)");
    312413
    313414        if (ret != LDB_SUCCESS) {
     
    317418        }
    318419
    319         if (res->count == 0 || res->msgs[0]->num_elements == 0)
     420        if (res->count == 0 || res->msgs[0]->num_elements == 0) {
     421                talloc_free(res);
    320422                return WERR_BADFILE;
    321 
    322         reg_ldb_unpack_value(mem_ctx,
    323                  res->msgs[0], name, data_type, data);
     423        }
     424
     425        if ((data_type != NULL) && (data != NULL)) {
     426                reg_ldb_unpack_value(mem_ctx, res->msgs[0], name, data_type,
     427                                     data);
     428        }
    324429
    325430        talloc_free(res);
     
    329434
    330435static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct hive_key *k,
    331                                   int idx, const char **name,
     436                                  uint32_t idx, const char **name,
    332437                                  uint32_t *data_type, DATA_BLOB *data)
    333438{
    334439        struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
    335440
    336         /* if default value exists, give it back */
     441        /* if the default value exists, give it back */
    337442        if (W_ERROR_IS_OK(ldb_get_default_value(mem_ctx, k, name, data_type,
    338443                data))) {
     
    361466{
    362467        struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
    363         struct ldb_context *c = kd->ldb;
    364         struct ldb_result *res;
    365         int ret;
    366         char *query;
    367 
    368         if (strlen(name) == 0) {
    369                 /* default value */
     468        const char *res_name;
     469        uint32_t idx;
     470
     471        /* the default value was requested, give it back */
     472        if (name[0] == '\0') {
    370473                return ldb_get_default_value(mem_ctx, k, NULL, data_type, data);
    371         } else {
    372                 /* normal value */
    373                 query = talloc_asprintf(mem_ctx, "(value=%s)", name);
    374                 ret = ldb_search(c, mem_ctx, &res, kd->dn, LDB_SCOPE_ONELEVEL, NULL, "%s", query);
    375                 talloc_free(query);
    376 
    377                 if (ret != LDB_SUCCESS) {
    378                         DEBUG(0, ("Error getting values for '%s': %s\n",
    379                                 ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
    380                         return WERR_FOOBAR;
    381                 }
    382 
    383                 if (res->count == 0)
    384                         return WERR_BADFILE;
    385 
    386                 reg_ldb_unpack_value(mem_ctx, res->msgs[0], NULL, data_type, data);
    387 
    388                 talloc_free(res);
    389         }
    390 
    391         return WERR_OK;
     474        }
     475
     476        /* Do the search if necessary */
     477        if (kd->values == NULL) {
     478                W_ERROR_NOT_OK_RETURN(cache_values(kd));
     479        }
     480
     481        for (idx = 0; idx < kd->value_count; idx++) {
     482                res_name = ldb_msg_find_attr_as_string(kd->values[idx], "value",
     483                                                       "");
     484                if (ldb_attr_cmp(name, res_name) == 0) {
     485                        reg_ldb_unpack_value(mem_ctx, kd->values[idx], NULL,
     486                                             data_type, data);
     487                        return WERR_OK;
     488                }
     489        }
     490
     491        return WERR_BADFILE;
    392492}
    393493
     
    396496{
    397497        struct ldb_result *res;
    398         struct ldb_dn *ldap_path;
     498        struct ldb_dn *ldb_path;
    399499        int ret;
    400500        struct ldb_key_data *newkd;
     
    402502        struct ldb_context *c = kd->ldb;
    403503
    404         ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
    405 
    406         ret = ldb_search(c, mem_ctx, &res, ldap_path, LDB_SCOPE_BASE, NULL, "(key=*)");
     504        ldb_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
     505        W_ERROR_HAVE_NO_MEMORY(ldb_path);
     506
     507        ret = ldb_search(c, mem_ctx, &res, ldb_path, LDB_SCOPE_BASE, NULL, "(key=*)");
    407508
    408509        if (ret != LDB_SUCCESS) {
    409510                DEBUG(3, ("Error opening key '%s': %s\n",
    410                         ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
     511                        ldb_dn_get_linearized(ldb_path), ldb_errstring(c)));
    411512                return WERR_FOOBAR;
    412513        } else if (res->count == 0) {
    413514                DEBUG(3, ("Key '%s' not found\n",
    414                         ldb_dn_get_linearized(ldap_path)));
     515                        ldb_dn_get_linearized(ldb_path)));
    415516                talloc_free(res);
    416517                return WERR_BADFILE;
     
    418519
    419520        newkd = talloc_zero(mem_ctx, struct ldb_key_data);
     521        W_ERROR_HAVE_NO_MEMORY(newkd);
    420522        newkd->key.ops = &reg_backend_ldb;
    421523        newkd->ldb = talloc_reference(newkd, kd->ldb);
    422         newkd->dn = ldb_dn_copy(mem_ctx, res->msgs[0]->dn);
     524        newkd->dn = ldb_dn_copy(newkd, res->msgs[0]->dn);
     525        newkd->classname = talloc_steal(newkd,
     526                                        ldb_msg_find_attr_as_string(res->msgs[0], "classname", NULL));
     527
     528        talloc_free(res);
    423529
    424530        *key = (struct hive_key *)newkd;
     
    442548
    443549        wrap = ldb_wrap_connect(parent_ctx, ev_ctx, lp_ctx,
    444                                 location, session_info, credentials, 0, NULL);
     550                                location, session_info, credentials, 0);
    445551
    446552        if (wrap == NULL) {
     
    477583{
    478584        struct ldb_key_data *parentkd = discard_const_p(struct ldb_key_data, parent);
     585        struct ldb_dn *ldb_path;
    479586        struct ldb_message *msg;
    480587        struct ldb_key_data *newkd;
    481588        int ret;
    482589
     590        ldb_path = reg_path_to_ldb(mem_ctx, parent, name, NULL);
     591        W_ERROR_HAVE_NO_MEMORY(ldb_path);
     592
    483593        msg = ldb_msg_new(mem_ctx);
    484 
    485         msg->dn = reg_path_to_ldb(msg, parent, name, NULL);
    486 
    487         ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name));
    488         if (classname != NULL)
    489                 ldb_msg_add_string(msg, "classname",
    490                                    talloc_strdup(mem_ctx, classname));
     594        W_ERROR_HAVE_NO_MEMORY(msg);
     595
     596        msg->dn = ldb_path;
     597
     598        ldb_msg_add_string(msg, "key", name);
     599        if (classname != NULL) {
     600                ldb_msg_add_string(msg, "classname", classname);
     601        }
    491602
    492603        ret = ldb_add(parentkd->ldb, msg);
     604
     605        talloc_free(msg);
     606
    493607        if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
    494608                return WERR_ALREADY_EXISTS;
     
    500614        }
    501615
    502         DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized(msg->dn)));
     616        DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized(ldb_path)));
    503617
    504618        newkd = talloc_zero(mem_ctx, struct ldb_key_data);
     619        W_ERROR_HAVE_NO_MEMORY(newkd);
    505620        newkd->ldb = talloc_reference(newkd, parentkd->ldb);
    506621        newkd->key.ops = &reg_backend_ldb;
    507         newkd->dn = talloc_steal(newkd, msg->dn);
     622        newkd->dn = talloc_steal(newkd, ldb_path);
     623        newkd->classname = talloc_steal(newkd, classname);
    508624
    509625        *newkey = (struct hive_key *)newkd;
     
    516632}
    517633
    518 static WERROR ldb_del_value (struct hive_key *key, const char *child)
     634static WERROR ldb_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key,
     635                            const char *child)
    519636{
    520637        int ret;
    521638        struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
    522         TALLOC_CTX *mem_ctx;
    523639        struct ldb_message *msg;
    524640        struct ldb_dn *childdn;
    525641
    526         if (strlen(child) == 0) {
     642        if (child[0] == '\0') {
    527643                /* default value */
    528                 mem_ctx = talloc_init("ldb_del_value");
    529 
    530644                msg = talloc_zero(mem_ctx, struct ldb_message);
     645                W_ERROR_HAVE_NO_MEMORY(msg);
    531646                msg->dn = ldb_dn_copy(msg, kd->dn);
     647                W_ERROR_HAVE_NO_MEMORY(msg->dn);
    532648                ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);
    533649                ldb_msg_add_empty(msg, "type", LDB_FLAG_MOD_DELETE, NULL);
    534650
    535651                ret = ldb_modify(kd->ldb, msg);
     652
     653                talloc_free(msg);
     654
    536655                if (ret != LDB_SUCCESS) {
    537656                        DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(kd->ldb)));
    538                         talloc_free(mem_ctx);
    539657                        return WERR_FOOBAR;
    540658                }
    541 
    542                 talloc_free(mem_ctx);
    543659        } else {
    544660                /* normal value */
     
    570686}
    571687
    572 static WERROR ldb_del_key(const struct hive_key *key, const char *name)
    573 {
    574         int i, ret;
     688static WERROR ldb_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *key,
     689                          const char *name)
     690{
     691        unsigned int i;
     692        int ret;
    575693        struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
    576         struct ldb_dn *ldap_path;
    577         TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key");
     694        struct ldb_dn *ldb_path;
    578695        struct ldb_context *c = parentkd->ldb;
    579696        struct ldb_result *res_keys;
     
    585702        werr = ldb_open_key(mem_ctx, key, name, &hk);
    586703        if (!W_ERROR_IS_OK(werr)) {
    587                 talloc_free(mem_ctx);
    588704                return werr;
    589705        }
    590706
    591         ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
    592         if (!ldap_path) {
    593                 talloc_free(mem_ctx);
    594                 return WERR_FOOBAR;
    595         }
     707        ldb_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
     708        W_ERROR_HAVE_NO_MEMORY(ldb_path);
    596709
    597710        /* Search for subkeys */
    598         ret = ldb_search(c, mem_ctx, &res_keys, ldap_path, LDB_SCOPE_ONELEVEL,
     711        ret = ldb_search(c, mem_ctx, &res_keys, ldb_path, LDB_SCOPE_ONELEVEL,
    599712                         NULL, "(key=*)");
    600713
    601714        if (ret != LDB_SUCCESS) {
    602715                DEBUG(0, ("Error getting subkeys for '%s': %s\n",
    603                       ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
    604                 talloc_free(mem_ctx);
     716                      ldb_dn_get_linearized(ldb_path), ldb_errstring(c)));
    605717                return WERR_FOOBAR;
    606718        }
    607719
    608720        /* Search for values */
    609         ret = ldb_search(c, mem_ctx, &res_vals, ldap_path, LDB_SCOPE_ONELEVEL,
     721        ret = ldb_search(c, mem_ctx, &res_vals, ldb_path, LDB_SCOPE_ONELEVEL,
    610722                         NULL, "(value=*)");
    611723
    612724        if (ret != LDB_SUCCESS) {
    613725                DEBUG(0, ("Error getting values for '%s': %s\n",
    614                       ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
    615                 talloc_free(mem_ctx);
     726                      ldb_dn_get_linearized(ldb_path), ldb_errstring(c)));
    616727                return WERR_FOOBAR;
    617728        }
     
    622733        if (ret != LDB_SUCCESS) {
    623734                DEBUG(0, ("ldb_transaction_start: %s\n", ldb_errstring(c)));
    624                 talloc_free(mem_ctx);
    625735                return WERR_FOOBAR;
    626736        }
     
    631741                for (i = 0; i < res_keys->count; i++)
    632742                {
    633                         werr = ldb_del_key(hk, ldb_msg_find_attr_as_string(
     743                        werr = ldb_del_key(mem_ctx, hk,
     744                                           ldb_msg_find_attr_as_string(
    634745                                                        res_keys->msgs[i],
    635746                                                        "key", NULL));
    636747                        if (!W_ERROR_IS_OK(werr)) {
    637748                                ret = ldb_transaction_cancel(c);
    638                                 talloc_free(mem_ctx);
    639749                                return werr;
    640750                        }
     
    644754                for (i = 0; i < res_vals->count; i++)
    645755                {
    646                         werr = ldb_del_value(hk, ldb_msg_find_attr_as_string(
     756                        werr = ldb_del_value(mem_ctx, hk,
     757                                             ldb_msg_find_attr_as_string(
    647758                                                        res_vals->msgs[i],
    648759                                                        "value", NULL));
    649760                        if (!W_ERROR_IS_OK(werr)) {
    650761                                ret = ldb_transaction_cancel(c);
    651                                 talloc_free(mem_ctx);
    652762                                return werr;
    653763                        }
    654764                }
    655765        }
     766        talloc_free(res_keys);
     767        talloc_free(res_vals);
    656768
    657769        /* Delete the key itself */
    658         ret = ldb_delete(c, ldap_path);
     770        ret = ldb_delete(c, ldb_path);
    659771
    660772        if (ret != LDB_SUCCESS)
     
    662774                DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(c)));
    663775                ret = ldb_transaction_cancel(c);
    664                 talloc_free(mem_ctx);
    665776                return WERR_FOOBAR;
    666777        }
     
    673784                DEBUG(0, ("ldb_transaction_commit: %s\n", ldb_errstring(c)));
    674785                ret = ldb_transaction_cancel(c);
    675                 talloc_free(mem_ctx);
    676                 return WERR_FOOBAR;
    677         }
    678 
    679         talloc_free(mem_ctx);
     786                return WERR_FOOBAR;
     787        }
    680788
    681789        /* reset cache */
     
    692800        struct ldb_message *msg;
    693801        struct ldb_key_data *kd = talloc_get_type(parent, struct ldb_key_data);
     802        unsigned int i;
    694803        int ret;
    695804        TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
    696805
    697806        msg = reg_ldb_pack_value(kd->ldb, mem_ctx, name, type, data);
     807        W_ERROR_HAVE_NO_MEMORY(msg);
     808
    698809        msg->dn = ldb_dn_copy(msg, kd->dn);
    699        
    700         if (strlen(name) > 0) {
     810        W_ERROR_HAVE_NO_MEMORY(msg->dn);
     811
     812        if (name[0] != '\0') {
    701813                /* For a default value, we add/overwrite the attributes to/of the hive.
    702                    For a normal value, we create new childs. */
     814                   For a normal value, we create a new child. */
    703815                if (!ldb_dn_add_child_fmt(msg->dn, "value=%s",
    704816                                  reg_ldb_escape(mem_ctx, name)))
     
    709821        }
    710822
    711         ret = ldb_add(kd->ldb, msg);
    712         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
    713                 int i;
    714                 for (i = 0; i < msg->num_elements; i++) {
    715                         if (msg->elements[i].flags != LDB_FLAG_MOD_DELETE)
    716                                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
    717                 }
    718                 ret = ldb_modify(kd->ldb, msg);
    719         }
     823        /* Try first a "modify" and if this doesn't work do try an "add" */
     824        for (i = 0; i < msg->num_elements; i++) {
     825                if (msg->elements[i].flags != LDB_FLAG_MOD_DELETE) {
     826                        msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
     827                }
     828        }
     829        ret = ldb_modify(kd->ldb, msg);
     830        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     831                i = 0;
     832                while (i < msg->num_elements) {
     833                        if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE) {
     834                                ldb_msg_remove_element(msg, &msg->elements[i]);
     835                        } else {
     836                                ++i;
     837                        }
     838                }
     839                ret = ldb_add(kd->ldb, msg);
     840        }
     841        if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
     842                /* ignore this -> the value didn't exist and also now doesn't */
     843                ret = LDB_SUCCESS;
     844        }
     845
     846        talloc_free(msg);
    720847
    721848        if (ret != LDB_SUCCESS) {
     
    744871{
    745872        struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
     873        uint32_t default_value_type = REG_NONE;
     874        DATA_BLOB default_value = { NULL, 0 };
     875        WERROR werr;
    746876
    747877        /* Initialization */
     
    761891                *max_valbufsize = 0;
    762892
     893        /* We need this to get the default value (if it exists) for counting
     894         * the values under the key and for finding out the longest value buffer
     895         * size. If no default value exists the DATA_BLOB "default_value" will
     896         * remain { NULL, 0 }. */
     897        werr = ldb_get_default_value(mem_ctx, key, NULL, &default_value_type,
     898                                     &default_value);
     899        if ((!W_ERROR_IS_OK(werr)) && (!W_ERROR_EQUAL(werr, WERR_BADFILE))) {
     900                return werr;
     901        }
     902
    763903        if (kd->subkeys == NULL) {
    764904                W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
    765905        }
    766 
    767906        if (kd->values == NULL) {
    768907                W_ERROR_NOT_OK_RETURN(cache_values(kd));
    769908        }
    770909
     910        if (classname != NULL) {
     911                *classname = kd->classname;
     912        }
     913
    771914        if (num_subkeys != NULL) {
    772915                *num_subkeys = kd->subkey_count;
     
    774917        if (num_values != NULL) {
    775918                *num_values = kd->value_count;
     919                /* also consider the default value if it exists */
     920                if (default_value.data != NULL) {
     921                        ++(*num_values);
     922                }
    776923        }
    777924
    778925
    779926        if (max_subkeynamelen != NULL) {
    780                 int i;
     927                unsigned int i;
    781928                struct ldb_message_element *el;
    782 
    783                 *max_subkeynamelen = 0;
    784929
    785930                for (i = 0; i < kd->subkey_count; i++) {
     
    790935
    791936        if (max_valnamelen != NULL || max_valbufsize != NULL) {
    792                 int i;
     937                unsigned int i;
    793938                struct ldb_message_element *el;
    794939                W_ERROR_NOT_OK_RETURN(cache_values(kd));
    795940
    796                 if (max_valbufsize != NULL)
    797                         *max_valbufsize = 0;
    798 
    799                 if (max_valnamelen != NULL)
    800                         *max_valnamelen = 0;
     941                /* also consider the default value if it exists */
     942                if ((max_valbufsize != NULL) && (default_value.data != NULL)) {
     943                                *max_valbufsize = MAX(*max_valbufsize,
     944                                                      default_value.length);
     945                }
    801946
    802947                for (i = 0; i < kd->value_count; i++) {
     
    809954                                uint32_t data_type;
    810955                                DATA_BLOB data;
    811                                 reg_ldb_unpack_value(mem_ctx, 
    812                                                      kd->values[i], NULL, 
     956                                reg_ldb_unpack_value(mem_ctx,
     957                                                     kd->values[i], NULL,
    813958                                                     &data_type, &data);
    814959                                *max_valbufsize = MAX(*max_valbufsize, data.length);
     
    817962                }
    818963        }
     964
     965        talloc_free(default_value.data);
    819966
    820967        return WERR_OK;
  • trunk/server/source4/lib/registry/local.c

    r414 r745  
    5858
    5959        local_key = talloc(ctx, struct local_key);
    60         local_key->hive_key = talloc_steal(local_key, hive);
    61         local_key->global.context = talloc_reference(local_key, ctx);
    62         local_key->path = parent_path;
     60        if (local_key != NULL) {
     61                local_key->hive_key = talloc_reference(local_key, hive);
     62                local_key->global.context = talloc_reference(local_key, ctx);
     63                local_key->path = parent_path;
     64        }
    6365
    6466        return (struct registry_key *)local_key;
     
    7173                             struct registry_key **result)
    7274{
    73         char *orig = talloc_strdup(mem_ctx, path),
    74                  *curbegin = orig,
    75                  *curend = strchr(orig, '\\');
     75        char *orig, *curbegin, *curend;
    7676        struct local_key *local_parent = talloc_get_type(parent,
    7777                                                         struct local_key);
     
    8181        int el;
    8282
     83        if (path == NULL) {
     84                return WERR_INVALID_PARAM;
     85        }
     86
     87        orig = talloc_strdup(mem_ctx, path);
     88        W_ERROR_HAVE_NO_MEMORY(orig);
     89        curbegin = orig;
     90        curend = strchr(orig, '\\');
     91
    8392        if (local_parent->path.elements != NULL) {
    8493                elements = talloc_array(mem_ctx, const char *,
    8594                                        str_list_length(local_parent->path.elements) + 1);
     95                W_ERROR_HAVE_NO_MEMORY(elements);
    8696                for (el = 0; local_parent->path.elements[el] != NULL; el++) {
    8797                        elements[el] = talloc_reference(elements,
     
    98108                        *curend = '\0';
    99109                elements = talloc_realloc(mem_ctx, elements, const char *, el+2);
     110                W_ERROR_HAVE_NO_MEMORY(elements);
    100111                elements[el] = talloc_strdup(elements, curbegin);
     112                W_ERROR_HAVE_NO_MEMORY(elements[el]);
    101113                el++;
    102114                elements[el] = NULL;
     
    159171
    160172static WERROR local_create_key(TALLOC_CTX *mem_ctx,
    161                                struct registry_key *parent_key,
    162                                const char *name,
     173                               struct registry_key *parent,
     174                               const char *path,
    163175                               const char *key_class,
    164176                               struct security_descriptor *security,
    165                                struct registry_key **key)
    166 {
    167         struct local_key *local_parent;
    168         struct hive_key *hivekey;
    169         const char **elements;
    170         int i;
    171         const char *last_part;
    172 
    173         last_part = strrchr(name, '\\');
    174         if (last_part == NULL) {
    175                 last_part = name;
    176                 local_parent = (struct local_key *)parent_key;
     177                               struct registry_key **result)
     178{
     179        char *orig, *curbegin, *curend;
     180        struct local_key *local_parent = talloc_get_type(parent,
     181                                                         struct local_key);
     182        struct hive_key *curkey = local_parent->hive_key;
     183        WERROR error;
     184        const char **elements = NULL;
     185        int el;
     186
     187        if (path == NULL) {
     188                return WERR_INVALID_PARAM;
     189        }
     190
     191        orig = talloc_strdup(mem_ctx, path);
     192        W_ERROR_HAVE_NO_MEMORY(orig);
     193        curbegin = orig;
     194        curend = strchr(orig, '\\');
     195
     196        if (local_parent->path.elements != NULL) {
     197                elements = talloc_array(mem_ctx, const char *,
     198                                        str_list_length(local_parent->path.elements) + 1);
     199                W_ERROR_HAVE_NO_MEMORY(elements);
     200                for (el = 0; local_parent->path.elements[el] != NULL; el++) {
     201                        elements[el] = talloc_reference(elements,
     202                                                        local_parent->path.elements[el]);
     203                }
     204                elements[el] = NULL;
    177205        } else {
    178                 W_ERROR_NOT_OK_RETURN(reg_open_key(mem_ctx, parent_key,
    179                                                    talloc_strndup(mem_ctx, name, last_part-name),
    180                                                    (struct registry_key **)&local_parent));
    181                 last_part++;
    182         }
    183 
    184         W_ERROR_NOT_OK_RETURN(hive_key_add_name(mem_ctx, local_parent->hive_key,
    185                                                 last_part, key_class, security,
    186                                                 &hivekey));
    187 
    188         if (local_parent->path.elements != NULL) {
    189                 elements = talloc_array(hivekey, const char *,
    190                                         str_list_length(local_parent->path.elements)+2);
    191                 for (i = 0; local_parent->path.elements[i] != NULL; i++) {
    192                         elements[i] = talloc_reference(elements,
    193                                                        local_parent->path.elements[i]);
    194                 }
    195         } else {
    196                 elements = talloc_array(hivekey, const char *, 2);
    197                 i = 0;
    198         }
    199 
    200         elements[i] = talloc_strdup(elements, name);
    201         elements[i+1] = NULL;
    202 
    203         *key = reg_import_hive_key(local_parent->global.context, hivekey,
    204                                    local_parent->path.predefined_key,
    205                                    elements);
     206                elements = NULL;
     207                el = 0;
     208        }
     209
     210        while (curbegin != NULL && *curbegin) {
     211                if (curend != NULL)
     212                        *curend = '\0';
     213                elements = talloc_realloc(mem_ctx, elements, const char *, el+2);
     214                W_ERROR_HAVE_NO_MEMORY(elements);
     215                elements[el] = talloc_strdup(elements, curbegin);
     216                W_ERROR_HAVE_NO_MEMORY(elements[el]);
     217                el++;
     218                elements[el] = NULL;
     219                error = hive_get_key_by_name(mem_ctx, curkey,
     220                                             curbegin, &curkey);
     221                if (W_ERROR_EQUAL(error, WERR_BADFILE)) {
     222                        error = hive_key_add_name(mem_ctx, curkey, curbegin,
     223                                                  key_class, security,
     224                                                  &curkey);
     225                }
     226                if (!W_ERROR_IS_OK(error)) {
     227                        DEBUG(2, ("Open/Creation of key %s failed: %s\n",
     228                                curbegin, win_errstr(error)));
     229                        talloc_free(orig);
     230                        return error;
     231                }
     232                if (curend == NULL)
     233                        break;
     234                curbegin = curend + 1;
     235                curend = strchr(curbegin, '\\');
     236        }
     237        talloc_free(orig);
     238
     239        *result = reg_import_hive_key(local_parent->global.context, curkey,
     240                                      local_parent->path.predefined_key,
     241                                      talloc_steal(curkey, elements));
    206242
    207243        return WERR_OK;
     
    212248{
    213249        struct local_key *local = (struct local_key *)key;
     250
     251        if (name == NULL) {
     252                return WERR_INVALID_PARAM;
     253        }
    214254
    215255        return hive_key_set_value(local->hive_key, name, type, data);
     
    221261{
    222262        const struct local_key *local = (const struct local_key *)key;
     263
     264        if (name == NULL) {
     265                return WERR_INVALID_PARAM;
     266        }
    223267
    224268        return hive_get_value(mem_ctx, local->hive_key, name, type, data);
     
    237281}
    238282
    239 static WERROR local_delete_key(struct registry_key *key, const char *name)
    240 {
    241         const struct local_key *local = (const struct local_key *)key;
    242 
    243         return hive_key_del(local->hive_key, name);
    244 }
    245 
    246 static WERROR local_delete_value(struct registry_key *key, const char *name)
    247 {
    248         const struct local_key *local = (const struct local_key *)key;
    249 
    250         return hive_key_del_value(local->hive_key, name);
     283static WERROR local_delete_key(TALLOC_CTX *mem_ctx, struct registry_key *key,
     284                               const char *name)
     285{
     286        const struct local_key *local = (const struct local_key *)key;
     287
     288        if (name == NULL) {
     289                return WERR_INVALID_PARAM;
     290        }
     291
     292        return hive_key_del(mem_ctx, local->hive_key, name);
     293}
     294
     295static WERROR local_delete_value(TALLOC_CTX *mem_ctx, struct registry_key *key,
     296                                 const char *name)
     297{
     298        const struct local_key *local = (const struct local_key *)key;
     299
     300        if (name == NULL) {
     301                return WERR_INVALID_PARAM;
     302        }
     303
     304        return hive_key_del_value(mem_ctx, local->hive_key, name);
    251305}
    252306
     
    328382        struct registry_local *reg_local = talloc_get_type(rctx,
    329383                                                           struct registry_local);
    330         struct mountpoint *mp = talloc(rctx, struct mountpoint);
    331         int i = 0;
    332 
     384        struct mountpoint *mp;
     385        unsigned int i = 0;
     386
     387        mp = talloc(rctx, struct mountpoint);
     388        W_ERROR_HAVE_NO_MEMORY(mp);
    333389        mp->path.predefined_key = key_id;
    334390        mp->prev = mp->next = NULL;
     
    337393                mp->path.elements = talloc_array(mp, const char *,
    338394                                                 str_list_length(elements));
     395                W_ERROR_HAVE_NO_MEMORY(mp->path.elements);
    339396                for (i = 0; elements[i] != NULL; i++) {
    340397                        mp->path.elements[i] = talloc_reference(mp->path.elements,
  • trunk/server/source4/lib/registry/man/regdiff.1.xml

    r414 r745  
    11<?xml version="1.0" encoding="iso-8859-1"?>
    2 <!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
     2<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
    33<refentry id="regdiff.1">
    44
  • trunk/server/source4/lib/registry/man/regpatch.1.xml

    r414 r745  
    11<?xml version="1.0" encoding="iso-8859-1"?>
    2 <!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
     2<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
    33<refentry id="regpatch.1">
    44
  • trunk/server/source4/lib/registry/man/regshell.1.xml

    r414 r745  
    11<?xml version="1.0" encoding="iso-8859-1"?>
    2 <!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
     2<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
    33<refentry id="regshell.1">
    44
  • trunk/server/source4/lib/registry/man/regtree.1.xml

    r414 r745  
    11<?xml version="1.0" encoding="iso-8859-1"?>
    2 <!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
     2<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
    33<refentry id="regtree.1">
    44
  • trunk/server/source4/lib/registry/patchfile.c

    r414 r745  
    55   Copyright (C) Jelmer Vernooij 2004-2007
    66   Copyright (C) Wilco Baan Hofman 2006
    7    Copyright (C) Matthias Dieter Wallnöfer 2008
     7   Copyright (C) Matthias Dieter Wallnöfer 2008-2010
    88
    99   This program is free software; you can redistribute it and/or modify
     
    2727
    2828_PUBLIC_ WERROR reg_preg_diff_load(int fd,
    29                                    struct smb_iconv_convenience *iconv_convenience,
    3029                                   const struct reg_diff_callbacks *callbacks,
    3130                                   void *callback_data);
    3231
    3332_PUBLIC_ WERROR reg_dotreg_diff_load(int fd,
    34                                      struct smb_iconv_convenience *iconv_convenience,
    3533                                     const struct reg_diff_callbacks *callbacks,
    3634                                     void *callback_data);
     
    4543                             void *callback_data)
    4644{
    47         int i;
     45        unsigned int i;
    4846        struct registry_key *t1 = NULL, *t2 = NULL;
    4947        char *tmppath;
     
    8785
    8886                if (!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_BADFILE)) {
    89                         DEBUG(0, ("Error occured while getting subkey by name: %s\n",
     87                        DEBUG(0, ("Error occurred while getting subkey by name: %s\n",
    9088                                win_errstr(error2)));
    9189                        talloc_free(mem_ctx);
     
    9694                /* didn't have such a subkey and therefore add a del diff */
    9795                tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1);
     96                if (tmppath == NULL) {
     97                        DEBUG(0, ("Out of memory\n"));
     98                        talloc_free(mem_ctx);
     99                        return WERR_NOMEM;
     100                }
    98101                if (!W_ERROR_IS_OK(error2))
    99102                        callbacks->del_key(callback_data, tmppath);
     
    102105                error1 = reg_open_key(mem_ctx, oldkey, keyname1, &t1);
    103106                if (!W_ERROR_IS_OK(error1)) {
    104                         DEBUG(0, ("Error occured while getting subkey by name: %s\n",
     107                        DEBUG(0, ("Error occurred while getting subkey by name: %s\n",
    105108                        win_errstr(error1)));
    106109                        talloc_free(mem_ctx);
     
    155158                }
    156159
    157                 /* oldkey didn't have such a subkey, add add diff */
     160                /* oldkey didn't have such a subkey, add a add diff */
    158161                tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1);
     162                if (tmppath == NULL) {
     163                        DEBUG(0, ("Out of memory\n"));
     164                        talloc_free(mem_ctx);
     165                        return WERR_NOMEM;
     166                }
    159167                callbacks->add_key(callback_data, tmppath);
    160168
     
    162170                error1 = reg_open_key(mem_ctx, newkey, keyname1, &t2);
    163171                if (!W_ERROR_IS_OK(error1)) {
    164                         DEBUG(0, ("Error occured while getting subkey by name: %s\n",
     172                        DEBUG(0, ("Error occurred while getting subkey by name: %s\n",
    165173                        win_errstr(error1)));
    166174                        talloc_free(mem_ctx);
     
    176184                const char *name;
    177185                uint32_t type1, type2;
    178                 DATA_BLOB contents1, contents2;
     186                DATA_BLOB contents1 = { NULL, 0 }, contents2 = { NULL, 0 };
    179187
    180188                error1 = reg_key_get_value_by_index(mem_ctx, newkey, i,
     
    203211
    204212                if (W_ERROR_IS_OK(error2)
    205                         && (data_blob_cmp(&contents1, &contents2) == 0)
    206                         && (type1 == type2))
     213                    && (data_blob_cmp(&contents1, &contents2) == 0)
     214                    && (type1 == type2)) {
     215                        talloc_free(discard_const_p(char, name));
     216                        talloc_free(contents1.data);
     217                        talloc_free(contents2.data);
    207218                        continue;
     219                }
    208220
    209221                callbacks->set_value(callback_data, path, name,
    210222                                     type1, contents1);
     223
     224                talloc_free(discard_const_p(char, name));
     225                talloc_free(contents1.data);
     226                talloc_free(contents2.data);
    211227        }
    212228
     
    215231                const char *name;
    216232                uint32_t type;
    217                 DATA_BLOB contents;
     233                DATA_BLOB contents = { NULL, 0 };
    218234
    219235                error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &name,
     
    232248                        error2 = WERR_BADFILE;
    233249
    234                 if (W_ERROR_IS_OK(error2))
     250                if (W_ERROR_IS_OK(error2)) {
     251                        talloc_free(discard_const_p(char, name));
     252                        talloc_free(contents.data);
    235253                        continue;
     254                }
    236255
    237256                if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) {
     
    243262
    244263                callbacks->del_value(callback_data, path, name);
     264
     265                talloc_free(discard_const_p(char, name));
     266                talloc_free(contents.data);
    245267        }
    246268
     
    257279                                  void *callback_data)
    258280{
    259         int i;
     281        unsigned int i;
    260282        WERROR error;
    261283
     
    281303                }
    282304
     305                /* if "r1" is NULL (old hive) and "r2" isn't (new hive) then
     306                 * the hive doesn't exist yet and we have to generate an add
     307                 * diff */
     308                if ((r1 == NULL) && (r2 != NULL)) {
     309                        callbacks->add_key(callback_data,
     310                                           reg_predefined_keys[i].name);
     311                }
     312                /* if "r1" isn't NULL (old hive) and "r2" is (new hive) then
     313                 * the hive shouldn't exist anymore and we have to generate a
     314                 * del diff */
     315                if ((r1 != NULL) && (r2 == NULL)) {
     316                        callbacks->del_key(callback_data,
     317                                           reg_predefined_keys[i].name);
     318                }
     319
    283320                error = reg_generate_diff_key(r1, r2,
    284321                        reg_predefined_keys[i].name, callbacks,
     
    300337 */
    301338_PUBLIC_ WERROR reg_diff_load(const char *filename,
    302                               struct smb_iconv_convenience *iconv_convenience,
    303339                              const struct reg_diff_callbacks *callbacks,
    304340                              void *callback_data)
     
    334370        if (strncmp(hdr, "PReg", 4) == 0) {
    335371                /* Must be a GPO Registry.pol file */
    336                 return reg_preg_diff_load(fd, iconv_convenience, callbacks, callback_data);
     372                return reg_preg_diff_load(fd, callbacks, callback_data);
    337373        } else {
    338374                /* Must be a normal .REG file */
    339                 return reg_dotreg_diff_load(fd, iconv_convenience, callbacks, callback_data);
     375                return reg_dotreg_diff_load(fd, callbacks, callback_data);
    340376        }
    341377}
     
    353389        /* Recursively create the path */
    354390        buf = talloc_strdup(ctx, key_name);
     391        W_ERROR_HAVE_NO_MEMORY(buf);
    355392        buf_ptr = buf;
    356393
     
    367404                        }
    368405                        *buf_ptr++ = '\\';
    369                 }
    370         }
     406                        talloc_free(tmp);
     407                }
     408        }
     409
     410        talloc_free(buf);
    371411
    372412        /* Add the key */
     
    379419                return error;
    380420        }
     421        talloc_free(tmp);
     422
    381423        return WERR_OK;
    382424}
     
    388430        /* We can't proof here for success, because a common superkey could */
    389431        /* have been deleted before the subkey's (diff order). This removed */
    390         /* therefore all childs recursively and the "WERR_BADFILE" result is */
     432        /* therefore all children recursively and the "WERR_BADFILE" result is */
    391433        /* expected. */
    392434
     
    420462        }
    421463
     464        talloc_free(tmp);
     465
    422466        return WERR_OK;
    423467}
     
    438482        }
    439483
    440         error = reg_del_value(tmp, value_name);
     484        error = reg_del_value(ctx, tmp, value_name);
    441485        if (!W_ERROR_IS_OK(error)) {
    442486                DEBUG(0, ("Error deleting value '%s'\n", value_name));
     
    444488        }
    445489
     490        talloc_free(tmp);
    446491
    447492        return WERR_OK;
     
    453498        struct registry_key *key;
    454499        WERROR error;
    455         const char* value_name;
     500        const char *value_name;
    456501
    457502        error = reg_open_key_abs(ctx, ctx, key_name, &key);
     
    467512        while (W_ERROR_IS_OK(reg_key_get_value_by_index(
    468513                        ctx, key, 0, &value_name, NULL, NULL))) {
    469                 error = reg_del_value(key, value_name);
     514                error = reg_del_value(ctx, key, value_name);
    470515                if (!W_ERROR_IS_OK(error)) {
    471516                        DEBUG(0, ("Error deleting value '%s'\n", value_name));
    472517                        return error;
    473518                }
    474         }
     519                talloc_free(discard_const_p(char, value_name));
     520        }
     521
     522        talloc_free(key);
    475523
    476524        return WERR_OK;
     
    481529 */
    482530_PUBLIC_ WERROR reg_diff_apply(struct registry_context *ctx,
    483                                                            struct smb_iconv_convenience *iconv_convenience,
    484531                                                           const char *filename)
    485532{
     
    493540        callbacks.done = NULL;
    494541
    495         return reg_diff_load(filename, iconv_convenience,
    496                              &callbacks, ctx);
    497 }
     542        return reg_diff_load(filename, &callbacks, ctx);
     543}
  • trunk/server/source4/lib/registry/patchfile_dotreg.c

    r414 r745  
    44
    55   Copyright (C) Jelmer Vernooij 2004-2007
    6    Copyright (C) Wilco Baan Hofman 2006-2008
     6   Copyright (C) Wilco Baan Hofman 2006-2010
    77
    88   This program is free software; you can redistribute it and/or modify
     
    2121*/
    2222
    23 /* FIXME Newer .REG files, created by Windows XP and above use unicode UCS-2 */
     23/* FIXME:
     24 * - Newer .REG files, created by Windows XP and above use unicode UCS-2
     25 * - @="" constructions should write value with empty name.
     26*/
    2427
    2528#include "includes.h"
     
    3639struct dotreg_data {
    3740        int fd;
    38         struct smb_iconv_convenience *iconv_convenience;
    3941};
     42
     43/*
     44 * This is basically a copy of data_blob_hex_string_upper, but with comma's
     45 * between the bytes in hex.
     46 */
     47static char *dotreg_data_blob_hex_string(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
     48{
     49        size_t i;
     50        char *hex_string;
     51
     52        hex_string = talloc_array(mem_ctx, char, (blob->length*3)+1);
     53        if (!hex_string) {
     54                return NULL;
     55        }
     56
     57        for (i = 0; i < blob->length; i++)
     58                slprintf(&hex_string[i*3], 4, "%02X,", blob->data[i]);
     59
     60        /* Remove last comma and NULL-terminate the string */
     61        hex_string[(blob->length*3)-1] = '\0';
     62        return hex_string;
     63}
     64
     65/*
     66 * This is basically a copy of reg_val_data_string, except that this function
     67 * has no 0x for dwords, everything else is regarded as binary, and binary
     68 * strings are represented with bytes comma-separated.
     69 */
     70static char *reg_val_dotreg_string(TALLOC_CTX *mem_ctx, uint32_t type,
     71                                   const DATA_BLOB data)
     72{
     73        char *ret = NULL;
     74
     75        if (data.length == 0)
     76                return talloc_strdup(mem_ctx, "");
     77
     78        switch (type) {
     79                case REG_EXPAND_SZ:
     80                case REG_SZ:
     81                        convert_string_talloc(mem_ctx,
     82                                                          CH_UTF16, CH_UNIX, data.data, data.length,
     83                                                          (void **)&ret, NULL, false);
     84                        break;
     85                case REG_DWORD:
     86                case REG_DWORD_BIG_ENDIAN:
     87                        SMB_ASSERT(data.length == sizeof(uint32_t));
     88                        ret = talloc_asprintf(mem_ctx, "%08x",
     89                                              IVAL(data.data, 0));
     90                        break;
     91                default: /* default means treat as binary */
     92                case REG_BINARY:
     93                        ret = dotreg_data_blob_hex_string(mem_ctx, &data);
     94                        break;
     95        }
     96
     97        return ret;
     98}
    4099
    41100static WERROR reg_dotreg_diff_add_key(void *_data, const char *key_name)
     
    62121{
    63122        struct dotreg_data *data = (struct dotreg_data *)_data;
    64 
    65         fdprintf(data->fd, "\"%s\"=%s:%s\n",
    66                         value_name, str_regtype(value_type),
    67                         reg_val_data_string(NULL, data->iconv_convenience, value_type, value));
     123        char *data_string = reg_val_dotreg_string(NULL,
     124                                                value_type, value);
     125        char *data_incl_type;
     126
     127        W_ERROR_HAVE_NO_MEMORY(data_string);
     128
     129        switch (value_type) {
     130                case REG_SZ:
     131                        data_incl_type = talloc_asprintf(data_string, "\"%s\"",
     132                                        data_string);
     133                        break;
     134                case REG_DWORD:
     135                        data_incl_type = talloc_asprintf(data_string,
     136                                        "dword:%s", data_string);
     137                        break;
     138                case REG_BINARY:
     139                        data_incl_type = talloc_asprintf(data_string, "hex:%s",
     140                                        data_string);
     141                        break;
     142                default:
     143                        data_incl_type = talloc_asprintf(data_string, "hex(%x):%s",
     144                                        value_type, data_string);
     145                        break;
     146        }
     147
     148        if (value_name[0] == '\0') {
     149                fdprintf(data->fd, "@=%s\n", data_incl_type);
     150        } else {
     151                fdprintf(data->fd, "\"%s\"=%s\n",
     152                         value_name, data_incl_type);
     153        }
     154
     155        talloc_free(data_string);
    68156
    69157        return WERR_OK;
     
    100188 */
    101189_PUBLIC_ WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename,
    102                                      struct smb_iconv_convenience *iconv_convenience,
    103190                                     struct reg_diff_callbacks **callbacks,
    104191                                     void **callback_data)
     
    108195        data = talloc_zero(ctx, struct dotreg_data);
    109196        *callback_data = data;
    110 
    111         data->iconv_convenience = iconv_convenience;
    112197
    113198        if (filename) {
     
    139224 */
    140225_PUBLIC_ WERROR reg_dotreg_diff_load(int fd,
    141                                      struct smb_iconv_convenience *iconv_convenience,
    142226                                     const struct reg_diff_callbacks *callbacks,
    143227                                     void *callback_data)
     
    148232        WERROR error;
    149233        uint32_t value_type;
    150         DATA_BLOB value;
     234        DATA_BLOB data;
     235        bool result;
     236        char *type_str = NULL;
     237        char *data_str;
     238        char *value;
     239        bool continue_next_line = 0;
    151240
    152241        line = afdgets(fd, mem_ctx, 0);
     
    159248
    160249        while ((line = afdgets(fd, mem_ctx, 0))) {
     250                /* Remove '\r' if it's a Windows text file */
     251                if (line[strlen(line)-1] == '\r') {
     252                        line[strlen(line)-1] = '\0';
     253                }
     254
    161255                /* Ignore comments and empty lines */
    162256                if (strlen(line) == 0 || line[0] == ';') {
     
    172266                /* Start of key */
    173267                if (line[0] == '[') {
    174                         p = strchr_m(line, ']');
    175                         if (p[strlen(p)-1] != ']') {
    176                                 DEBUG(0, ("Missing ']'\n"));
    177                                 return WERR_GENERAL_FAILURE;
    178                         }
     268                        if (line[strlen(line)-1] != ']') {
     269                                DEBUG(0, ("Missing ']' on line: %s\n", line));
     270                                talloc_free(line);
     271                                continue;
     272                        }
     273
    179274                        /* Deleting key */
    180275                        if (line[1] == '-') {
    181276                                curkey = talloc_strndup(line, line+2, strlen(line)-3);
     277                                W_ERROR_HAVE_NO_MEMORY(curkey);
    182278
    183279                                error = callbacks->del_key(callback_data,
    184280                                                           curkey);
     281
    185282                                if (!W_ERROR_IS_OK(error)) {
    186283                                        DEBUG(0,("Error deleting key %s\n",
     
    195292                        }
    196293                        curkey = talloc_strndup(mem_ctx, line+1, strlen(line)-2);
     294                        W_ERROR_HAVE_NO_MEMORY(curkey);
    197295
    198296                        error = callbacks->add_key(callback_data, curkey);
     
    208306
    209307                /* Deleting/Changing value */
    210                 p = strchr_m(line, '=');
    211                 if (p == NULL) {
    212                         DEBUG(0, ("Malformed line\n"));
    213                         talloc_free(line);
    214                         continue;
    215                 }
    216 
    217                 *p = '\0'; p++;
    218 
    219                 if (curkey == NULL) {
    220                         DEBUG(0, ("Value change without key\n"));
    221                         talloc_free(line);
    222                         continue;
    223                 }
    224 
    225                 /* Delete value */
    226                 if (strcmp(p, "-") == 0) {
    227                         error = callbacks->del_value(callback_data,
    228                                                      curkey, line);
    229                         if (!W_ERROR_IS_OK(error)) {
    230                                 DEBUG(0, ("Error deleting value %s in key %s\n",
    231                                         line, curkey));
    232                                 talloc_free(mem_ctx);
    233                                 return error;
    234                         }
    235 
    236                         talloc_free(line);
    237                         continue;
    238                 }
    239 
    240                 q = strchr_m(p, ':');
    241                 if (q) {
    242                         *q = '\0';
    243                         q++;
    244                 }
    245 
    246                 reg_string_to_val(line, iconv_convenience,
    247                                   q?p:"REG_SZ", q?q:p,
    248                                   &value_type, &value);
    249 
    250                 error = callbacks->set_value(callback_data, curkey, line,
    251                                              value_type, value);
     308                if (continue_next_line) {
     309                        continue_next_line = 0;
     310
     311                        /* Continued data start with two whitespaces */
     312                        if (line[0] != ' ' || line[1] != ' ') {
     313                                DEBUG(0, ("Malformed line: %s\n", line));
     314                                talloc_free(line);
     315                                continue;
     316                        }
     317                        p = line + 2;
     318
     319                        /* Continue again if line ends with a backslash */
     320                        if (line[strlen(line)-1] == '\\') {
     321                                line[strlen(line)-1] = '\0';
     322                                continue_next_line = 1;
     323                                data_str = talloc_strdup_append(data_str, p);
     324                                talloc_free(line);
     325                                continue;
     326                        }
     327                        data_str = talloc_strdup_append(data_str, p);
     328                } else {
     329                        p = strchr_m(line, '=');
     330                        if (p == NULL) {
     331                                DEBUG(0, ("Malformed line: %s\n", line));
     332                                talloc_free(line);
     333                                continue;
     334                        }
     335
     336                        *p = '\0'; p++;
     337
     338
     339                        if (curkey == NULL) {
     340                                DEBUG(0, ("Value change without key\n"));
     341                                talloc_free(line);
     342                                continue;
     343                        }
     344
     345                        /* Values should be double-quoted */
     346                        if (line[0] != '"') {
     347                                DEBUG(0, ("Malformed line\n"));
     348                                talloc_free(line);
     349                                continue;
     350                        }
     351
     352                        /* Chop of the quotes and store as value */
     353                        value = talloc_strndup(mem_ctx, line+1,strlen(line)-2);
     354
     355                        /* Delete value */
     356                        if (p[0] == '-') {
     357                                error = callbacks->del_value(callback_data,
     358                                                     curkey, value);
     359
     360                                /* Ignore if key does not exist (WERR_BADFILE)
     361                                 * Consistent with Windows behaviour */
     362                                if (!W_ERROR_IS_OK(error) &&
     363                                    !W_ERROR_EQUAL(error, WERR_BADFILE)) {
     364                                        DEBUG(0, ("Error deleting value %s in key %s\n",
     365                                                value, curkey));
     366                                        talloc_free(mem_ctx);
     367                                        return error;
     368                                }
     369
     370                                talloc_free(line);
     371                                talloc_free(value);
     372                                continue;
     373                        }
     374
     375                        /* Do not look for colons in strings */
     376                        if (p[0] == '"') {
     377                                q = NULL;
     378                                data_str = talloc_strndup(mem_ctx, p+1,strlen(p)-2);
     379                        } else {
     380                                /* Split the value type from the data */
     381                                q = strchr_m(p, ':');
     382                                if (q) {
     383                                        *q = '\0';
     384                                        q++;
     385                                        type_str = talloc_strdup(mem_ctx, p);
     386                                        data_str = talloc_strdup(mem_ctx, q);
     387                                } else {
     388                                        data_str = talloc_strdup(mem_ctx, p);
     389                                }
     390                        }
     391
     392                        /* Backslash before the CRLF means continue on next line */
     393                        if (data_str[strlen(data_str)-1] == '\\') {
     394                                data_str[strlen(data_str)-1] = '\0';
     395                                talloc_free(line);
     396                                continue_next_line = 1;
     397                                continue;
     398                        }
     399                }
     400                DEBUG(9, ("About to write %s with type %s, length %ld: %s\n", value, type_str, (long) strlen(data_str), data_str));
     401                result = reg_string_to_val(value,
     402                                  type_str?type_str:"REG_SZ", data_str,
     403                                  &value_type, &data);
     404                if (!result) {
     405                        DEBUG(0, ("Error converting string to value for line:\n%s\n",
     406                                        line));
     407                        return WERR_GENERAL_FAILURE;
     408                }
     409
     410                error = callbacks->set_value(callback_data, curkey, value,
     411                                             value_type, data);
    252412                if (!W_ERROR_IS_OK(error)) {
    253413                        DEBUG(0, ("Error setting value for %s in %s\n",
    254                                 line, curkey));
     414                                value, curkey));
    255415                        talloc_free(mem_ctx);
    256416                        return error;
    257417                }
    258418
     419                /* Clean up buffers */
     420                if (type_str != NULL) {
     421                        talloc_free(type_str);
     422                        type_str = NULL;
     423                }
     424                talloc_free(data_str);
     425                talloc_free(value);
    259426                talloc_free(line);
    260427        }
     
    262429        close(fd);
    263430
    264         return WERR_OK;
    265 }
     431        talloc_free(mem_ctx);
     432
     433        return WERR_OK;
     434}
  • trunk/server/source4/lib/registry/patchfile_preg.c

    r414 r745  
    3434        uint16_t v;
    3535
    36         if (read(fd, &v, 2) < 2) {
     36        if (read(fd, &v, sizeof(uint16_t)) < sizeof(uint16_t)) {
    3737                return WERR_GENERAL_FAILURE;
    3838        }
     
    4242static WERROR preg_write_utf16(int fd, const char *string)
    4343{
    44         codepoint_t v;
    45         uint16_t i;
    46         size_t size;
     44        uint16_t v;
     45        size_t i, size;
    4746
    4847        for (i = 0; i < strlen(string); i+=size) {
    4948                v = next_codepoint(&string[i], &size);
    50                 if (write(fd, &v, 2) < 2) {
     49                if (write(fd, &v, sizeof(uint16_t)) < sizeof(uint16_t)) {
    5150                        return WERR_GENERAL_FAILURE;
    5251                }
     
    8988        char *parent_name;
    9089        DATA_BLOB blob;
    91 
    92         parent_name = talloc_strndup(data->ctx, key_name, strrchr(key_name, '\\')-key_name);
    93         blob.data = (uint8_t *)talloc_strndup(data->ctx, key_name+(strrchr(key_name, '\\')-key_name)+1,
    94                         strlen(key_name)-(strrchr(key_name, '\\')-key_name));
     90        WERROR werr;
     91
     92        parent_name = talloc_strndup(data->ctx, key_name,
     93                                     strrchr(key_name, '\\')-key_name);
     94        W_ERROR_HAVE_NO_MEMORY(parent_name);
     95        blob.data = (uint8_t*)talloc_strndup(data->ctx,
     96                                             key_name+(strrchr(key_name, '\\')-key_name)+1,
     97                                             strlen(key_name)-(strrchr(key_name, '\\')-key_name));
     98        W_ERROR_HAVE_NO_MEMORY(blob.data);
    9599        blob.length = strlen((char *)blob.data)+1;
    96100       
    97101
    98102        /* FIXME: These values should be accumulated to be written at done(). */
    99         return reg_preg_diff_set_value(data, parent_name, "**DeleteKeys", REG_SZ, blob);
     103        werr = reg_preg_diff_set_value(data, parent_name, "**DeleteKeys",
     104                                       REG_SZ, blob);
     105
     106        talloc_free(parent_name);
     107        talloc_free(blob.data);
     108
     109        return werr;
    100110}
    101111
     
    106116        char *val;
    107117        DATA_BLOB blob;
     118        WERROR werr;
    108119
    109120        val = talloc_asprintf(data->ctx, "**Del.%s", value_name);
    110 
     121        W_ERROR_HAVE_NO_MEMORY(val);
    111122        blob.data = (uint8_t *)talloc(data->ctx, uint32_t);
    112         *(uint32_t *)blob.data = 0;
    113         blob.length = 4;
    114         return reg_preg_diff_set_value(data, key_name, val, REG_DWORD, blob);
     123        W_ERROR_HAVE_NO_MEMORY(blob.data);
     124        SIVAL(blob.data, 0, 0);
     125        blob.length = sizeof(uint32_t);
     126
     127        werr = reg_preg_diff_set_value(data, key_name, val, REG_DWORD, blob);
     128
     129        talloc_free(val);
     130        talloc_free(blob.data);
     131
     132        return werr;
    115133}
    116134
     
    119137        struct preg_data *data = (struct preg_data *)_data;
    120138        DATA_BLOB blob;
     139        WERROR werr;
    121140
    122141        blob.data = (uint8_t *)talloc(data->ctx, uint32_t);
    123         *(uint32_t *)blob.data = 0;     
    124         blob.length = 4;
    125 
    126         return reg_preg_diff_set_value(data, key_name, "**DelVals.", REG_DWORD, blob);
     142        W_ERROR_HAVE_NO_MEMORY(blob.data);
     143        SIVAL(blob.data, 0, 0);
     144        blob.length = sizeof(uint32_t);
     145
     146        werr = reg_preg_diff_set_value(data, key_name, "**DelVals.", REG_DWORD,
     147                                       blob);
     148
     149        talloc_free(blob.data);
     150
     151        return werr;
    127152}
    128153
     
    140165 */
    141166_PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename,
    142                                    struct smb_iconv_convenience *ic,
    143167                                   struct reg_diff_callbacks **callbacks,
    144168                                   void **callback_data)
     
    165189
    166190        strncpy(preg_header.hdr, "PReg", 4);
    167         SIVAL(&preg_header, 4, 1);
    168         write(data->fd, (uint8_t *)&preg_header,8);
     191        SIVAL(&preg_header.version, 0, 1);
     192        write(data->fd, (uint8_t *)&preg_header, sizeof(preg_header));
    169193
    170194        data->ctx = ctx;
     
    185209 */
    186210_PUBLIC_ WERROR reg_preg_diff_load(int fd,
    187                                    struct smb_iconv_convenience *iconv_convenience,
    188211                                   const struct reg_diff_callbacks *callbacks,
    189212                                   void *callback_data)
     
    206229
    207230        /* Read first 8 bytes (the header) */
    208         if (read(fd, &preg_header, 8) != 8) {
     231        if (read(fd, &preg_header, sizeof(preg_header)) != sizeof(preg_header)) {
    209232                DEBUG(0, ("Could not read PReg file: %s\n",
    210233                                strerror(errno)));
     
    255278
    256279                /* Get the type */
    257                 if (read(fd, &value_type, 4) < 4) {
     280                if (read(fd, &value_type, sizeof(uint32_t)) < sizeof(uint32_t)) {
    258281                        DEBUG(0, ("Error while reading PReg\n"));
    259282                        ret = WERR_GENERAL_FAILURE;
     
    270293                        goto cleanup;
    271294                }
     295
    272296                /* Get data length */
    273                 if (read(fd, &length, 4) < 4) {
     297                if (read(fd, &length, sizeof(uint32_t)) < sizeof(uint32_t)) {
    274298                        DEBUG(0, ("Error while reading PReg\n"));
    275299                        ret = WERR_GENERAL_FAILURE;
    276300                        goto cleanup;
    277301                }
     302                length = IVAL(&length, 0);
     303
    278304                /* Read past delimiter */
    279305                buf_ptr = buf;
     
    284310                        goto cleanup;
    285311                }
     312
    286313                /* Get the data */
    287314                buf_ptr = buf;
  • trunk/server/source4/lib/registry/pyregistry.c

    r414 r745  
    33   Samba utility functions
    44   Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
     5   Copyright (C) Wilco Baan Hofman <wilco@baanhofman.nl> 2010
    56   
    67   This program is free software; you can redistribute it and/or modify
     
    1819*/
    1920
     21#include <Python.h>
    2022#include "includes.h"
    21 #include <tevent.h>
    22 #include <Python.h>
    2323#include "libcli/util/pyerrors.h"
    2424#include "lib/registry/registry.h"
    25 #include "scripting/python/modules.h" /* for py_iconv_convenience() */
    26 #include <pytalloc.h>
     25#include "lib/talloc/pytalloc.h"
     26#include "lib/events/events.h"
    2727#include "auth/credentials/pycredentials.h"
    2828#include "param/pyparam.h"
    2929
    30 #ifndef Py_RETURN_NONE
    31 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
    32 #endif
    33 
    34 PyAPI_DATA(PyTypeObject) PyRegistryKey;
    35 PyAPI_DATA(PyTypeObject) PyRegistry;
    36 PyAPI_DATA(PyTypeObject) PyHiveKey;
     30extern PyTypeObject PyRegistryKey;
     31extern PyTypeObject PyRegistry;
     32extern PyTypeObject PyHiveKey;
    3733
    3834/*#define PyRegistryKey_AsRegistryKey(obj) py_talloc_get_type(obj, struct registry_key)*/
     
    9692                return NULL;
    9793
    98         result = reg_diff_apply(ctx, py_iconv_convenience(NULL), filename);
     94        result = reg_diff_apply(ctx, filename);
    9995        PyErr_WERROR_IS_ERR_RAISE(result);
    10096
     
    164160        .tp_new = registry_new,
    165161        .tp_basicsize = sizeof(py_talloc_Object),
    166         .tp_dealloc = py_talloc_dealloc,
    167162        .tp_flags = Py_TPFLAGS_DEFAULT,
    168163};
     
    177172                return NULL;
    178173
    179         result = hive_key_del(key, name);
     174        result = hive_key_del(NULL, key, name);
    180175
    181176        PyErr_WERROR_IS_ERR_RAISE(result);
     
    204199                return NULL;
    205200
    206         result = hive_key_del_value(key, name);
     201        result = hive_key_del_value(NULL, key, name);
    207202
    208203        PyErr_WERROR_IS_ERR_RAISE(result);
     
    225220                result = hive_key_set_value(key, name, type, value);
    226221        else
    227                 result = hive_key_del_value(key, name);
     222                result = hive_key_del_value(NULL, key, name);
    228223
    229224        PyErr_WERROR_IS_ERR_RAISE(result);
     
    244239};
    245240
    246 static PyObject *hive_open(PyTypeObject *type, PyObject *args, PyObject *kwargs)
    247 {
    248         /* reg_open_hive */
     241static PyObject *hive_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
    249242        Py_RETURN_NONE;
     243}
     244
     245static PyObject *py_open_hive(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     246{
     247        const char *kwnames[] = { "location", "lp_ctx", "session_info", "credentials", NULL };
     248        WERROR result;
     249        struct loadparm_context *lp_ctx;
     250        PyObject *py_lp_ctx, *py_session_info, *py_credentials;
     251        struct auth_session_info *session_info;
     252        struct cli_credentials *credentials;
     253        char *location;
     254        struct hive_key *hive_key;
     255        TALLOC_CTX *mem_ctx;
     256
     257        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOO",
     258                                         discard_const_p(char *, kwnames),
     259                                         &location,
     260                                         &py_lp_ctx, &py_session_info,
     261                                         &py_credentials))
     262                return NULL;
     263
     264        mem_ctx = talloc_new(NULL);
     265        if (mem_ctx == NULL) {
     266                PyErr_NoMemory();
     267                return NULL;
     268        }
     269
     270        lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     271        if (lp_ctx == NULL) {
     272                PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
     273                talloc_free(mem_ctx);
     274                return NULL;
     275        }
     276
     277        credentials = cli_credentials_from_py_object(py_credentials);
     278        if (credentials == NULL) {
     279                PyErr_SetString(PyExc_TypeError, "Expected credentials");
     280                talloc_free(mem_ctx);
     281                return NULL;
     282        }
     283        session_info = NULL;
     284
     285        result = reg_open_hive(NULL, location, session_info, credentials,
     286                               tevent_context_init(NULL),
     287                               lp_ctx, &hive_key);
     288        talloc_free(mem_ctx);
     289        PyErr_WERROR_IS_ERR_RAISE(result);
     290
     291        return py_talloc_steal(&PyHiveKey, hive_key);
    250292}
    251293
     
    253295        .tp_name = "HiveKey",
    254296        .tp_methods = hive_key_methods,
    255         .tp_new = hive_open,
     297        .tp_new = hive_new,
    256298        .tp_basicsize = sizeof(py_talloc_Object),
    257         .tp_dealloc = py_talloc_dealloc,
    258299        .tp_flags = Py_TPFLAGS_DEFAULT,
    259300};
     
    262303        .tp_name = "RegistryKey",
    263304        .tp_basicsize = sizeof(py_talloc_Object),
    264         .tp_dealloc = py_talloc_dealloc,
    265305        .tp_flags = Py_TPFLAGS_DEFAULT,
    266306};
     
    271311        struct registry_context *reg_ctx;
    272312        WERROR result;
    273     struct loadparm_context *lp_ctx;
     313        struct loadparm_context *lp_ctx;
    274314        PyObject *py_lp_ctx, *py_session_info, *py_credentials;
    275315        struct auth_session_info *session_info;
    276     struct cli_credentials *credentials;
    277         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO", discard_const_p(char *, kwnames),
    278                                          &py_lp_ctx, &py_session_info, &py_credentials))
    279                 return NULL;
    280 
    281     lp_ctx = lp_from_py_object(py_lp_ctx);
    282     if (lp_ctx == NULL) {
     316        struct cli_credentials *credentials;
     317        TALLOC_CTX *mem_ctx;
     318
     319        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO",
     320                                         discard_const_p(char *, kwnames),
     321                                         &py_lp_ctx, &py_session_info,
     322                                         &py_credentials))
     323                return NULL;
     324
     325        mem_ctx = talloc_new(NULL);
     326        if (mem_ctx == NULL) {
     327                PyErr_NoMemory();
     328                return NULL;
     329        }
     330
     331        lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     332        if (lp_ctx == NULL) {
    283333                PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
    284                 return NULL;
    285     }
     334                talloc_free(mem_ctx);
     335                return NULL;
     336        }
    286337
    287338        credentials = cli_credentials_from_py_object(py_credentials);
    288339        if (credentials == NULL) {
    289340                PyErr_SetString(PyExc_TypeError, "Expected credentials");
     341                talloc_free(mem_ctx);
    290342                return NULL;
    291343        }
     
    295347        result = reg_open_samba(NULL, &reg_ctx, NULL,
    296348                                lp_ctx, session_info, credentials);
     349        talloc_free(mem_ctx);
    297350        if (!W_ERROR_IS_OK(result)) {
    298351                PyErr_SetWERROR(result);
    299352                return NULL;
    300353        }
    301        
     354
    302355        return py_talloc_steal(&PyRegistry, reg_ctx);
    303356}
     
    339392        WERROR result;
    340393        char *location;
    341     struct loadparm_context *lp_ctx;
    342     struct cli_credentials *credentials;
     394        struct loadparm_context *lp_ctx;
     395        struct cli_credentials *credentials;
    343396        struct hive_key *key;
    344397        struct auth_session_info *session_info;
     398        TALLOC_CTX *mem_ctx;
    345399
    346400        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOO",
    347                                                                          discard_const_p(char *, kwnames),
    348                                                                          &location,
    349                                                                          &py_session_info, &py_credentials,
    350                                                                          &py_lp_ctx))
    351                 return NULL;
    352 
    353     lp_ctx = lp_from_py_object(py_lp_ctx);
    354     if (lp_ctx == NULL) {
     401                                         discard_const_p(char *, kwnames),
     402                                         &location, &py_session_info,
     403                                         &py_credentials, &py_lp_ctx))
     404                return NULL;
     405
     406        mem_ctx = talloc_new(NULL);
     407        if (mem_ctx == NULL) {
     408                PyErr_NoMemory();
     409                return NULL;
     410        }
     411
     412        lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     413        if (lp_ctx == NULL) {
    355414                PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
    356                 return NULL;
    357     }
     415                talloc_free(mem_ctx);
     416                return NULL;
     417        }
    358418
    359419        credentials = cli_credentials_from_py_object(py_credentials);
    360420        if (credentials == NULL) {
    361421                PyErr_SetString(PyExc_TypeError, "Expected credentials");
     422                talloc_free(mem_ctx);
    362423                return NULL;
    363424        }
     
    366427
    367428        result = reg_open_ldb_file(NULL, location, session_info, credentials,
    368                                                            tevent_context_init(NULL), lp_ctx, &key);
     429                                   s4_event_context_init(NULL), lp_ctx, &key);
     430        talloc_free(mem_ctx);
    369431        PyErr_WERROR_IS_ERR_RAISE(result);
    370432
     
    401463        { "create_directory", py_create_directory, METH_VARARGS, "create_dir(location) -> key" },
    402464        { "open_ldb", (PyCFunction)py_open_ldb_file, METH_VARARGS|METH_KEYWORDS, "open_ldb(location, session_info=None, credentials=None, loadparm_context=None) -> key" },
     465        { "open_hive", (PyCFunction)py_open_hive, METH_VARARGS|METH_KEYWORDS, "open_hive(location, session_info=None, credentials=None, loadparm_context=None) -> key" },
    403466        { "str_regtype", py_str_regtype, METH_VARARGS, "str_regtype(int) -> str" },
    404467        { "get_predef_name", py_get_predef_name, METH_VARARGS, "get_predef_name(hkey) -> str" },
     
    409472{
    410473        PyObject *m;
     474        PyTypeObject *talloc_type = PyTalloc_GetObjectType();
     475
     476        if (talloc_type == NULL)
     477                return;
     478
     479        PyHiveKey.tp_base = talloc_type;
     480        PyRegistry.tp_base = talloc_type;
     481        PyRegistryKey.tp_base = talloc_type;
    411482
    412483        if (PyType_Ready(&PyHiveKey) < 0)
  • trunk/server/source4/lib/registry/regf.c

    r414 r745  
    33   Registry backend for REGF files
    44   Copyright (C) 2005-2007 Jelmer Vernooij, jelmer@samba.org
    5    Copyright (C) 2006 Wilco Baan Hofman, wilco@baanhofman.nl
     5   Copyright (C) 2006-2010 Wilco Baan Hofman, wilco@baanhofman.nl
    66
    77   This program is free software; you can redistribute it and/or modify
     
    5050        struct hbin_block **hbins;
    5151        struct regf_hdr *header;
    52         struct smb_iconv_convenience *iconv_convenience;
     52        time_t last_write;
    5353};
    5454
    55 static WERROR regf_save_hbin(struct regf_data *data);
     55static WERROR regf_save_hbin(struct regf_data *data, bool flush);
    5656
    5757struct regf_key_data {
     
    6565                                         uint32_t offset, uint32_t *rel_offset)
    6666{
    67         int i;
     67        unsigned int i;
    6868
    6969        for (i = 0; data->hbins[i]; i++) {
     
    8787{
    8888        uint32_t checksum = 0, x;
    89         int i;
     89        unsigned int i;
    9090
    9191        for (i = 0; i < 0x01FB; i+= 4) {
     
    112112
    113113        if (hbin == NULL) {
    114                 DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset));
     114                DEBUG(1, ("Can't find HBIN at 0x%04x\n", offset));
    115115                return ret;
    116116        }
     
    135135                         TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p)
    136136{
    137         struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
     137        struct tdr_pull *pull = tdr_pull_init(regf);
    138138
    139139        pull->data = hbin_get(regf, offset);
     
    160160{
    161161        DATA_BLOB ret;
    162         uint32_t rel_offset = -1; /* Relative offset ! */
     162        uint32_t rel_offset = (uint32_t) -1; /* Relative offset ! */
    163163        struct hbin_block *hbin = NULL;
    164         int i;
     164        unsigned int i;
    165165
    166166        *offset = 0;
     
    218218                DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n",
    219219                        size));
     220
     221                /* Add extra hbin block */
    220222                data->hbins = talloc_realloc(data, data->hbins,
    221223                                             struct hbin_block *, i+2);
     
    226228                data->hbins[i+1] = NULL;
    227229
     230                /* Set hbin data */
    228231                hbin->HBIN_ID = talloc_strdup(hbin, "hbin");
    229232                hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next);
    230233                hbin->offset_to_next = 0x1000;
    231234                hbin->unknown[0] = 0;
    232                 hbin->unknown[0] = 0;
     235                hbin->unknown[1] = 0;
    233236                unix_to_nt_time(&hbin->last_change, time(NULL));
    234237                hbin->block_size = hbin->offset_to_next;
    235238                hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20);
    236 
     239                /* Update the regf header */
     240                data->header->last_block += hbin->offset_to_next;
     241
     242                /* Set the next block to it's proper size and set the
     243                 * rel_offset for this block */
     244                SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
    237245                rel_offset = 0x0;
    238                 SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
    239246        }
    240247
     
    262269        memcpy(dest.data, blob.data, blob.length);
    263270
     271        /* Make sure that we have no tailing garbage in the block */
     272        if (dest.length > blob.length) {
     273                memset(dest.data + blob.length, 0, dest.length - blob.length);
     274        }
     275
    264276        return ret;
    265277}
     
    268280                               tdr_push_fn_t push_fn, void *p)
    269281{
    270         struct tdr_push *push = tdr_push_init(data, data->iconv_convenience);
     282        struct tdr_push *push = tdr_push_init(data);
    271283        uint32_t ret;
    272284
     
    311323
    312324        /* If the next block is free, merge into big free block */
    313         if (rel_offset + size < hbin->offset_to_next) {
     325        if (rel_offset + size < hbin->offset_to_next - 0x20) {
    314326                next_size = IVALS(hbin->data, rel_offset+size);
    315327                if (next_size > 0) {
     
    336348        int32_t needed_size;
    337349        int32_t possible_size;
    338         int i;
     350        unsigned int i;
    339351
    340352        SMB_ASSERT(orig_offset > 0);
     
    395407                                      uint32_t orig_offset, void *p)
    396408{
    397         struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience);
     409        struct tdr_push *push = tdr_push_init(regf);
    398410        uint32_t ret;
    399411
     
    451463                                                    (char*)data.data,
    452464                                                    private_data->nk->clsname_length);
     465                        W_ERROR_HAVE_NO_MEMORY(*classname);
    453466                } else
    454467                        *classname = NULL;
     
    485498        if (!hbin_get_tdr(regf, offset, nk,
    486499                          (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
    487                 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
     500                DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n", offset));
    488501                return NULL;
    489502        }
     
    500513
    501514static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
    502                              int idx, const char **name,
     515                             uint32_t idx, const char **name,
    503516                             uint32_t *data_type, DATA_BLOB *data)
    504517{
     
    515528        tmp = hbin_get(regf, private_data->nk->values_offset);
    516529        if (!tmp.data) {
    517                 DEBUG(0, ("Unable to find value list\n"));
     530                DEBUG(0, ("Unable to find value list at 0x%x\n",
     531                                private_data->nk->values_offset));
    518532                return WERR_GENERAL_FAILURE;
    519533        }
     
    530544        if (!hbin_get_tdr(regf, vk_offset, vk,
    531545                          (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
    532                 DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
     546                DEBUG(0, ("Unable to get VK block at 0x%x\n", vk_offset));
    533547                talloc_free(vk);
    534548                return WERR_GENERAL_FAILURE;
     
    536550
    537551        /* FIXME: name character set ?*/
    538         if (name != NULL)
     552        if (name != NULL) {
    539553                *name = talloc_strndup(ctx, vk->data_name, vk->name_length);
     554                W_ERROR_HAVE_NO_MEMORY(*name);
     555        }
    540556
    541557        if (data_type != NULL)
     
    543559
    544560        if (vk->data_length & 0x80000000) {
    545                 vk->data_length &=~0x80000000;
    546                 data->data = (uint8_t *)talloc_memdup(ctx, (uint8_t *)&vk->data_offset, vk->data_length);
    547                 data->length = vk->data_length;
     561                /* this is data of type "REG_DWORD" or "REG_DWORD_BIG_ENDIAN" */
     562                data->data = talloc_size(ctx, sizeof(uint32_t));
     563                W_ERROR_HAVE_NO_MEMORY(data->data);
     564                SIVAL(data->data, 0, vk->data_offset);
     565                data->length = sizeof(uint32_t);
    548566        } else {
    549567                *data = hbin_get(regf, vk->data_offset);
     
    563581                                     uint32_t *type, DATA_BLOB *data)
    564582{
    565         int i;
     583        unsigned int i;
    566584        const char *vname;
    567585        WERROR error;
     
    598616                return WERR_NO_MORE_ITEMS;
    599617
     618        /* Make sure that we don't crash if the key is empty */
     619        if (nk->subkeys_offset == -1) {
     620                return WERR_NO_MORE_ITEMS;
     621        }
     622
    600623        data = hbin_get(private_data->hive, nk->subkeys_offset);
    601624        if (!data.data) {
    602                 DEBUG(0, ("Unable to find subkey list\n"));
     625                DEBUG(0, ("Unable to find subkey list at 0x%x\n",
     626                        nk->subkeys_offset));
    603627                return WERR_GENERAL_FAILURE;
    604628        }
     
    606630        if (!strncmp((char *)data.data, "li", 2)) {
    607631                struct li_block li;
    608                 struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
     632                struct tdr_pull *pull = tdr_pull_init(private_data->hive);
    609633
    610634                DEBUG(10, ("Subkeys in LI list\n"));
     
    627651        } else if (!strncmp((char *)data.data, "lf", 2)) {
    628652                struct lf_block lf;
    629                 struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
     653                struct tdr_pull *pull = tdr_pull_init(private_data->hive);
    630654
    631655                DEBUG(10, ("Subkeys in LF list\n"));
     
    648672        } else if (!strncmp((char *)data.data, "lh", 2)) {
    649673                struct lh_block lh;
    650                 struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
     674                struct tdr_pull *pull = tdr_pull_init(private_data->hive);
    651675
    652676                DEBUG(10, ("Subkeys in LH list\n"));
     
    668692        } else if (!strncmp((char *)data.data, "ri", 2)) {
    669693                struct ri_block ri;
    670                 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
     694                struct tdr_pull *pull = tdr_pull_init(ctx);
    671695                uint16_t i;
    672696                uint16_t sublist_count = 0;
     
    769793                                                    (char*)db.data,
    770794                                                    ret->nk->clsname_length);
     795                        W_ERROR_HAVE_NO_MEMORY(*classname);
    771796                } else
    772797                        *classname = NULL;
     
    801826        }
    802827
    803         pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
     828        pull = tdr_pull_init(ctx);
    804829
    805830        pull->data = subkey_data;
     
    836861        uint32_t key_off = 0;
    837862
     863        /* Make sure that we don't crash if the key is empty */
     864        if (nk->subkeys_offset == -1) {
     865                return WERR_BADFILE;
     866        }
     867
    838868        data = hbin_get(private_data->hive, nk->subkeys_offset);
    839869        if (!data.data) {
     
    844874        if (!strncmp((char *)data.data, "li", 2)) {
    845875                struct li_block li;
    846                 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
     876                struct tdr_pull *pull = tdr_pull_init(ctx);
    847877                uint16_t i;
    848878
     
    875905        } else if (!strncmp((char *)data.data, "lf", 2)) {
    876906                struct lf_block lf;
    877                 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
     907                struct tdr_pull *pull = tdr_pull_init(ctx);
    878908                uint16_t i;
    879909
     
    910940        } else if (!strncmp((char *)data.data, "lh", 2)) {
    911941                struct lh_block lh;
    912                 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
     942                struct tdr_pull *pull = tdr_pull_init(ctx);
    913943                uint16_t i;
    914944                uint32_t hash;
     
    947977        } else if (!strncmp((char *)data.data, "ri", 2)) {
    948978                struct ri_block ri;
    949                 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
     979                struct tdr_pull *pull = tdr_pull_init(ctx);
    950980                uint16_t i, j;
    951981
     
    10521082
    10531083        /* Push the security descriptor to a blob */
    1054         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL,
     1084        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf,
    10551085                                                          sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
    10561086                DEBUG(0, ("Unable to push security descriptor\n"));
     
    12051235        data.data = sk.sec_desc;
    12061236        data.length = sk.rec_size;
    1207         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, NULL, *sd,
     1237        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, *sd,
    12081238                                                  (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) {
    12091239                DEBUG(0, ("Error parsing security descriptor\n"));
     
    12891319
    12901320        if (!strncmp((char *)data.data, "li", 2)) {
    1291                 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
     1321                struct tdr_pull *pull = tdr_pull_init(regf);
    12921322                struct li_block li;
     1323                struct nk_block sub_nk;
     1324                int32_t i, j;
    12931325
    12941326                pull->data = data;
     
    13071339                }
    13081340
     1341                /*
     1342                 * Find the position to store the pointer
     1343                 * Extensive testing reveils that at least on windows 7 subkeys
     1344                 * *MUST* be stored in alphabetical order
     1345                 */
     1346                for (i = 0; i < li.key_count; i++) {
     1347                        /* Get the nk */
     1348                        hbin_get_tdr(regf, li.nk_offset[i], regf,
     1349                                        (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk);
     1350                        if (strcasecmp(name, sub_nk.key_name) < 0) {
     1351                                break;
     1352                        }
     1353                }
     1354
    13091355                li.nk_offset = talloc_realloc(regf, li.nk_offset,
    13101356                                              uint32_t, li.key_count+1);
    13111357                W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
    1312                 li.nk_offset[li.key_count] = key_offset;
     1358
     1359                /* Move everything behind this offset */
     1360                for (j = li.key_count - 1; j >= i; j--) {
     1361                        li.nk_offset[j+1] = li.nk_offset[j];
     1362                }
     1363                       
     1364                li.nk_offset[i] = key_offset;
    13131365                li.key_count++;
    13141366                *ret = hbin_store_tdr_resize(regf,
     
    13181370                talloc_free(li.nk_offset);
    13191371        } else if (!strncmp((char *)data.data, "lf", 2)) {
    1320                 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
     1372                struct tdr_pull *pull = tdr_pull_init(regf);
    13211373                struct lf_block lf;
     1374                struct nk_block sub_nk;
     1375                int32_t i, j;
    13221376
    13231377                pull->data = data;
     
    13311385                SMB_ASSERT(!strncmp(lf.header, "lf", 2));
    13321386
     1387                /*
     1388                 * Find the position to store the hash record
     1389                 * Extensive testing reveils that at least on windows 7 subkeys
     1390                 * *MUST* be stored in alphabetical order
     1391                 */
     1392                for (i = 0; i < lf.key_count; i++) {
     1393                        /* Get the nk */
     1394                        hbin_get_tdr(regf, lf.hr[i].nk_offset, regf,
     1395                                        (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk);
     1396                        if (strcasecmp(name, sub_nk.key_name) < 0) {
     1397                                break;
     1398                        }
     1399                }
     1400
    13331401                lf.hr = talloc_realloc(regf, lf.hr, struct hash_record,
    13341402                                       lf.key_count+1);
    13351403                W_ERROR_HAVE_NO_MEMORY(lf.hr);
    1336                 lf.hr[lf.key_count].nk_offset = key_offset;
    1337                 lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4);
     1404
     1405                /* Move everything behind this hash record */
     1406                for (j = lf.key_count - 1; j >= i; j--) {
     1407                        lf.hr[j+1] = lf.hr[j];
     1408                }
     1409
     1410                lf.hr[i].nk_offset = key_offset;
     1411                lf.hr[i].hash = talloc_strndup(lf.hr, name, 4);
    13381412                W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash);
    13391413                lf.key_count++;
     
    13441418                talloc_free(lf.hr);
    13451419        } else if (!strncmp((char *)data.data, "lh", 2)) {
    1346                 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
     1420                struct tdr_pull *pull = tdr_pull_init(regf);
    13471421                struct lh_block lh;
     1422                struct nk_block sub_nk;
     1423                int32_t i, j;
    13481424
    13491425                pull->data = data;
     
    13571433                SMB_ASSERT(!strncmp(lh.header, "lh", 2));
    13581434
     1435                /*
     1436                 * Find the position to store the hash record
     1437                 * Extensive testing reveils that at least on windows 7 subkeys
     1438                 * *MUST* be stored in alphabetical order
     1439                 */
     1440                for (i = 0; i < lh.key_count; i++) {
     1441                        /* Get the nk */
     1442                        hbin_get_tdr(regf, lh.hr[i].nk_offset, regf,
     1443                                        (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk);
     1444                        if (strcasecmp(name, sub_nk.key_name) < 0) {
     1445                                break;
     1446                        }
     1447                }
     1448
    13591449                lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash,
    13601450                                       lh.key_count+1);
    13611451                W_ERROR_HAVE_NO_MEMORY(lh.hr);
    1362                 lh.hr[lh.key_count].nk_offset = key_offset;
    1363                 lh.hr[lh.key_count].base37 = regf_create_lh_hash(name);
     1452
     1453                /* Move everything behind this hash record */
     1454                for (j = lh.key_count - 1; j >= i; j--) {
     1455                        lh.hr[j+1] = lh.hr[j];
     1456                }
     1457
     1458                lh.hr[i].nk_offset = key_offset;
     1459                lh.hr[i].base37 = regf_create_lh_hash(name);
    13641460                lh.key_count++;
    13651461                *ret = hbin_store_tdr_resize(regf,
     
    13931489        if (strncmp((char *)data.data, "li", 2) == 0) {
    13941490                struct li_block li;
    1395                 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
     1491                struct tdr_pull *pull = tdr_pull_init(regf);
    13961492                uint16_t i;
    13971493                bool found_offset = false;
     
    14371533        } else if (strncmp((char *)data.data, "lf", 2) == 0) {
    14381534                struct lf_block lf;
    1439                 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
     1535                struct tdr_pull *pull = tdr_pull_init(regf);
    14401536                uint16_t i;
    14411537                bool found_offset = false;
     
    14831579        } else if (strncmp((char *)data.data, "lh", 2) == 0) {
    14841580                struct lh_block lh;
    1485                 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
     1581                struct tdr_pull *pull = tdr_pull_init(regf);
    14861582                uint16_t i;
    14871583                bool found_offset = false;
     
    15381634}
    15391635
    1540 static WERROR regf_del_value (struct hive_key *key, const char *name)
     1636static WERROR regf_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key,
     1637                             const char *name)
    15411638{
    15421639        struct regf_key_data *private_data = (struct regf_key_data *)key;
     
    15471644        bool found_offset = false;
    15481645        DATA_BLOB values;
    1549         uint32_t i;
     1646        unsigned int i;
    15501647
    15511648        if (nk->values_offset == -1) {
     
    15921689                              private_data->offset, nk);
    15931690
    1594         return regf_save_hbin(private_data->hive);
    1595 }
    1596 
    1597 
    1598 static WERROR regf_del_key(const struct hive_key *parent, const char *name)
     1691        return regf_save_hbin(private_data->hive, 0);
     1692}
     1693
     1694
     1695static WERROR regf_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent,
     1696                           const char *name)
    15991697{
    16001698        const struct regf_key_data *private_data =
     
    16231721                char *sk_name;
    16241722                struct hive_key *sk = (struct hive_key *)key;
    1625                 int i = key->nk->num_subkeys;
     1723                unsigned int i = key->nk->num_subkeys;
    16261724                while (i--) {
    16271725                        /* Get subkey information. */
     
    16351733
    16361734                        /* Delete subkey. */
    1637                         error = regf_del_key(sk, sk_name);
     1735                        error = regf_del_key(NULL, sk, sk_name);
    16381736                        if (!W_ERROR_IS_OK(error)) {
    16391737                                DEBUG(0, ("Can't delete key '%s'.\n", sk_name));
     
    16491747                struct hive_key *sk = (struct hive_key *)key;
    16501748                DATA_BLOB data;
    1651                 int i = key->nk->num_values;
     1749                unsigned int i = key->nk->num_values;
    16521750                while (i--) {
    16531751                        /* Get value information. */
     
    16611759
    16621760                        /* Delete value. */
    1663                         error = regf_del_value(sk, val_name);
     1761                        error = regf_del_value(NULL, sk, val_name);
    16641762                        if (!W_ERROR_IS_OK(error)) {
    16651763                                DEBUG(0, ("Can't delete value '%s'.\n", val_name));
     
    16901788        hbin_free(private_data->hive, key->offset);
    16911789
    1692         return regf_save_hbin(private_data->hive);
     1790        return regf_save_hbin(private_data->hive, 0);
    16931791}
    16941792
     
    17171815        nk.num_values = 0;
    17181816        nk.values_offset = -1;
    1719         memset(nk.unk3, 0, 5);
     1817        memset(nk.unk3, 0, sizeof(nk.unk3));
    17201818        nk.clsname_offset = -1; /* FIXME: fill in */
    17211819        nk.clsname_length = 0;
     
    17281826        if (!hbin_get_tdr(regf, regf->header->data_offset, root,
    17291827                          (tdr_pull_fn_t)tdr_pull_nk_block, root)) {
    1730                 DEBUG(0, ("Unable to find HBIN data for offset %d\n",
     1828                DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n",
    17311829                        regf->header->data_offset));
    17321830                return WERR_GENERAL_FAILURE;
     
    17531851        *ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
    17541852
    1755         return regf_save_hbin(private_data->hive);
     1853        DEBUG(9, ("Storing key %s\n", name));
     1854        return regf_save_hbin(private_data->hive, 0);
    17561855}
    17571856
     
    17641863        struct vk_block vk;
    17651864        uint32_t i;
    1766         uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1;
     1865        uint32_t tmp_vk_offset, vk_offset, old_vk_offset = (uint32_t) -1;
    17671866        DATA_BLOB values;
    17681867
     
    17781877                                          (tdr_pull_fn_t)tdr_pull_vk_block,
    17791878                                          &vk)) {
    1780                                 DEBUG(0, ("Unable to get VK block at %d\n",
     1879                                DEBUG(0, ("Unable to get VK block at 0x%x\n",
    17811880                                        tmp_vk_offset));
    17821881                                return WERR_GENERAL_FAILURE;
     
    17871886                        }
    17881887                }
    1789                 /* Free data, if any */
    1790                 if (!(vk.data_length & 0x80000000)) {
    1791                         hbin_free(regf, vk.data_offset);
    1792                 }
    1793         }
     1888        }
     1889
     1890        /* If it's new, create the vk struct, if it's old, free the old data. */
    17941891        if (old_vk_offset == -1) {
    17951892                vk.header = "vk";
     
    18021899                        vk.flag = 0;
    18031900                }
    1804         }
     1901        } else {
     1902                /* Free data, if any */
     1903                if (!(vk.data_length & 0x80000000)) {
     1904                        hbin_free(regf, vk.data_offset);
     1905                }
     1906        }
     1907
    18051908        /* Set the type and data */
    18061909        vk.data_length = data.length;
    18071910        vk.data_type = type;
    1808         if (type == REG_DWORD) {
     1911        if ((type == REG_DWORD) || (type == REG_DWORD_BIG_ENDIAN)) {
     1912                if (vk.data_length != sizeof(uint32_t)) {
     1913                        DEBUG(0, ("DWORD or DWORD_BIG_ENDIAN value with size other than 4 byte!\n"));
     1914                        return WERR_NOT_SUPPORTED;
     1915                }
    18091916                vk.data_length |= 0x80000000;
    1810                 vk.data_offset = *(uint32_t *)data.data;
     1917                vk.data_offset = IVAL(data.data, 0);
    18111918        } else {
    18121919                /* Store data somewhere */
     
    18641971                              (tdr_push_fn_t) tdr_push_nk_block,
    18651972                              private_data->offset, nk);
    1866         return regf_save_hbin(private_data->hive);
    1867 }
    1868 
    1869 static WERROR regf_save_hbin(struct regf_data *regf)
    1870 {
    1871         struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience);
    1872         int i;
     1973        return regf_save_hbin(private_data->hive, 0);
     1974}
     1975
     1976static WERROR regf_save_hbin(struct regf_data *regf, bool flush)
     1977{
     1978        struct tdr_push *push = tdr_push_init(regf);
     1979        unsigned int i;
    18731980
    18741981        W_ERROR_HAVE_NO_MEMORY(push);
     1982
     1983        /* Only write once every 5 seconds, or when flush is set */
     1984        if (!flush && regf->last_write + 5 >= time(NULL)) {
     1985                return WERR_OK;
     1986        }
     1987
     1988        regf->last_write = time(NULL);
    18751989
    18761990        if (lseek(regf->fd, 0, SEEK_SET) == -1) {
     
    18872001        talloc_free(push);
    18882002
    1889         if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,
     2003        if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd,
    18902004                                            (tdr_push_fn_t)tdr_push_regf_hdr,
    18912005                                            regf->header))) {
     
    19002014
    19012015        for (i = 0; regf->hbins[i]; i++) {
    1902                 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,
     2016                if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd,
    19032017                                                    (tdr_push_fn_t)tdr_push_hbin_block,
    19042018                                                    regf->hbins[i]))) {
     
    19122026
    19132027WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
    1914                             struct smb_iconv_convenience *iconv_convenience,
    19152028                            const char *location,
    19162029                            int minor_version, struct hive_key **key)
     
    19262039
    19272040        regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
    1928 
    1929         regf->iconv_convenience = iconv_convenience;
    19302041
    19312042        W_ERROR_HAVE_NO_MEMORY(regf);
     
    19632074
    19642075        nk.header = "nk";
    1965         nk.type = REG_SUB_KEY;
     2076        nk.type = REG_ROOT_KEY;
    19662077        unix_to_nt_time(&nk.last_change, time(NULL));
    19672078        nk.uk1 = 0;
     
    19972108       
    19982109        /* Push the security descriptor to a blob */
    1999         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL,
     2110        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf,
    20002111                                     sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
    20012112                DEBUG(0, ("Unable to push security descriptor\n"));
     
    20282139                                               regf->header->data_offset);
    20292140
    2030         error = regf_save_hbin(regf);
     2141        error = regf_save_hbin(regf, 1);
    20312142        if (!W_ERROR_IS_OK(error)) {
    20322143                return error;
     
    20342145       
    20352146        /* We can drop our own reference now that *key will have created one */
    2036         talloc_free(regf);
     2147        talloc_unlink(NULL, regf);
    20372148
    20382149        return WERR_OK;
    20392150}
    20402151
     2152static WERROR regf_flush_key(struct hive_key *key)
     2153{
     2154        struct regf_key_data *private_data = (struct regf_key_data *)key;
     2155        struct regf_data *regf = private_data->hive;
     2156        WERROR error;
     2157
     2158        error = regf_save_hbin(regf, 1);
     2159        if (!W_ERROR_IS_OK(error)) {
     2160                DEBUG(0, ("Failed to flush regf to disk\n"));
     2161                return error;
     2162        }
     2163
     2164        return WERR_OK;
     2165}
     2166
     2167static int regf_destruct(struct regf_data *regf)
     2168{
     2169        WERROR error;
     2170
     2171        /* Write to disk */
     2172        error = regf_save_hbin(regf, 1);
     2173        if (!W_ERROR_IS_OK(error)) {
     2174                DEBUG(0, ("Failed to flush registry to disk\n"));
     2175                return -1;
     2176        }
     2177
     2178        /* Close file descriptor */
     2179        close(regf->fd);
     2180
     2181        return 0;
     2182}
     2183
    20412184WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location,
    2042                           struct smb_iconv_convenience *iconv_convenience, struct hive_key **key)
     2185                          struct hive_key **key)
    20432186{
    20442187        struct regf_data *regf;
    20452188        struct regf_hdr *regf_hdr;
    20462189        struct tdr_pull *pull;
    2047         int i;
     2190        unsigned int i;
    20482191
    20492192        regf = (struct regf_data *)talloc_zero(parent_ctx, struct regf_data);
    2050 
    2051         regf->iconv_convenience = iconv_convenience;
    2052 
    20532193        W_ERROR_HAVE_NO_MEMORY(regf);
     2194
     2195        talloc_set_destructor(regf, regf_destruct);
    20542196
    20552197        DEBUG(5, ("Attempting to load registry file\n"));
     
    20652207        }
    20662208
    2067         pull = tdr_pull_init(regf, regf->iconv_convenience);
     2209        pull = tdr_pull_init(regf);
    20682210
    20692211        pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, 0, regf);
     
    21632305        .del_key = regf_del_key,
    21642306        .delete_value = regf_del_value,
     2307        .flush_key = regf_flush_key
    21652308};
  • trunk/server/source4/lib/registry/regf.idl

    r414 r745  
    2525        [noprint] struct regf_version {
    2626                [value(1)] uint32 major;
    27                 [value(3)] uint32 minor;
     27                uint32 minor;
    2828                [value(0)] uint32 release;
    2929                [value(1)] uint32 build;
     
    7575
    7676        [noprint] enum reg_key_type {
    77                 REG_ROOT_KEY = 0x20,
    78                 REG_SUB_KEY  = 0x2C,
     77                REG_ROOT_KEY = 0x2C,
     78                REG_SUB_KEY  = 0x20,
    7979                REG_SYM_LINK = 0x10
    8080        };
  • trunk/server/source4/lib/registry/registry.h

    r414 r745  
    2424struct registry_context;
    2525struct loadparm_context;
    26 struct smb_iconv_convenience;
    2726
    2827#include <talloc.h>
     
    7170         */
    7271        WERROR (*add_key) (TALLOC_CTX *ctx,
    73                            const struct hive_key *parent_key, const char *name,
     72                           const struct hive_key *parent_key, const char *path,
    7473                           const char *classname,
    7574                           struct security_descriptor *desc,
     
    7877         * Remove an existing key.
    7978         */
    80         WERROR (*del_key) (const struct hive_key *key, const char *name);
     79        WERROR (*del_key) (TALLOC_CTX *mem_ctx,
     80                           const struct hive_key *key, const char *name);
    8181
    8282        /**
     
    8989         */
    9090        WERROR (*enum_value) (TALLOC_CTX *mem_ctx,
    91                               struct hive_key *key, int idx,
     91                              struct hive_key *key, uint32_t idx,
    9292                              const char **name, uint32_t *type,
    9393                              DATA_BLOB *data);
     
    109109         * Remove a value.
    110110         */
    111         WERROR (*delete_value) (struct hive_key *key, const char *name);
     111        WERROR (*delete_value) (TALLOC_CTX *mem_ctx,
     112                                struct hive_key *key, const char *name);
    112113
    113114        /* Security Descriptors */
     
    167168                         struct security_descriptor *desc,
    168169                         struct hive_key **key);
    169 WERROR hive_key_del(const struct hive_key *key, const char *name);
     170WERROR hive_key_del(TALLOC_CTX *mem_ctx,
     171                    const struct hive_key *key, const char *name);
    170172WERROR hive_get_key_by_name(TALLOC_CTX *mem_ctx,
    171173                            const struct hive_key *key, const char *name,
     
    194196                         const struct security_descriptor *security);
    195197
    196 WERROR hive_key_del_value(struct hive_key *key, const char *name);
     198WERROR hive_key_del_value(TALLOC_CTX *mem_ctx,
     199                          struct hive_key *key, const char *name);
    197200
    198201WERROR hive_key_flush(struct hive_key *key);
     
    203206                          const char *location, struct hive_key **key);
    204207WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx,
    205                           const char *location, struct smb_iconv_convenience *iconv_convenience,
    206                           struct hive_key **key);
     208                          const char *location, struct hive_key **key);
    207209WERROR reg_open_ldb_file(TALLOC_CTX *parent_ctx, const char *location,
    208210                         struct auth_session_info *session_info,
     
    216218                            const char *location, struct hive_key **key);
    217219WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
    218                             struct smb_iconv_convenience *iconv_convenience,
    219220                            const char *location,
    220221                            int major_version,
     
    305306                              struct registry_key **key);
    306307
    307         WERROR (*delete_key) (struct registry_key *key, const char *name);
    308 
    309         WERROR (*delete_value) (struct registry_key *key, const char *name);
     308        WERROR (*delete_key) (TALLOC_CTX *mem_ctx,
     309                              struct registry_key *key, const char *name);
     310
     311        WERROR (*delete_value) (TALLOC_CTX *mem_ctx,
     312                                struct registry_key *key, const char *name);
    310313
    311314        WERROR (*enum_key) (TALLOC_CTX *mem_ctx,
     
    412415WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx,
    413416                                   const struct registry_key *key,
    414                                    int idx,
     417                                   uint32_t idx,
    415418                                   const char **name,
    416419                                   const char **classname,
     
    425428                                 uint32_t *type,
    426429                                 DATA_BLOB *data);
    427 WERROR reg_key_del(struct registry_key *parent, const char *name);
     430WERROR reg_key_del(TALLOC_CTX *mem_ctx,
     431                   struct registry_key *parent, const char *name);
    428432WERROR reg_key_add_name(TALLOC_CTX *mem_ctx,
    429433                        struct registry_key *parent, const char *name,
     
    435439WERROR reg_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key,
    436440                        struct security_descriptor **secdesc);
    437 WERROR reg_del_value(struct registry_key *key, const char *valname);
     441WERROR reg_del_value(TALLOC_CTX *mem_ctx,
     442                     struct registry_key *key, const char *valname);
    438443WERROR reg_key_flush(struct registry_key *key);
    439444WERROR reg_create_key(TALLOC_CTX *mem_ctx,
     
    446451/* Utility functions */
    447452const char *str_regtype(int type);
    448 char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, uint32_t type, const DATA_BLOB data);
    449 char *reg_val_description(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, const char *name,
     453bool push_reg_sz(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *s);
     454bool push_reg_multi_sz(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char **a);
     455bool pull_reg_sz(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, const char **s);
     456bool pull_reg_multi_sz(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, const char ***a);
     457int regtype_by_string(const char *str);
     458char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, const DATA_BLOB data);
     459char *reg_val_description(TALLOC_CTX *mem_ctx, const char *name,
    450460                          uint32_t type, const DATA_BLOB data);
    451 bool reg_string_to_val(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, const char *type_str,
     461bool reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str,
    452462                       const char *data_str, uint32_t *type, DATA_BLOB *data);
    453463WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle,
     
    486496
    487497WERROR reg_diff_apply(struct registry_context *ctx,
    488                                           struct smb_iconv_convenience *ic, const char *filename);
     498                                          const char *filename);
    489499
    490500WERROR reg_generate_diff(struct registry_context *ctx1,
     
    493503                         void *callback_data);
    494504WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename,
    495                             struct smb_iconv_convenience *iconv_convenience,
    496505                            struct reg_diff_callbacks **callbacks,
    497506                            void **callback_data);
    498507WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename,
    499                           struct smb_iconv_convenience *ic,
    500508                          struct reg_diff_callbacks **callbacks,
    501509                          void **callback_data);
     
    506514                             void *callback_data);
    507515WERROR reg_diff_load(const char *filename,
    508                      struct smb_iconv_convenience *iconv_convenience,
    509516                     const struct reg_diff_callbacks *callbacks,
    510517                     void *callback_data);
    511518
    512519WERROR reg_dotreg_diff_load(int fd,
    513                                      struct smb_iconv_convenience *iconv_convenience,
    514520                                     const struct reg_diff_callbacks *callbacks,
    515521                                     void *callback_data);
    516522
    517523WERROR reg_preg_diff_load(int fd,
    518                    struct smb_iconv_convenience *iconv_convenience,
    519524                                   const struct reg_diff_callbacks *callbacks,
    520525                                   void *callback_data);
  • trunk/server/source4/lib/registry/registry.pc.in

    r414 r745  
    88Requires: talloc
    99Requires.private: ldb
    10 Version: 0.0.1
    11 Libs: -L${libdir} -lregistry
     10Version: @PACKAGE_VERSION@
     11Libs: @LIB_RPATH@ -L${libdir} -lregistry
    1212Cflags: -I${includedir}  -DHAVE_IMMEDIATE_STRUCTURES=1
  • trunk/server/source4/lib/registry/rpc.c

    r414 r745  
    2828        struct registry_key key;
    2929        struct policy_handle pol;
    30         struct dcerpc_pipe *pipe;
    31 
     30        struct dcerpc_binding_handle *binding_handle;
    3231        const char* classname; 
    3332        uint32_t num_subkeys;
     
    4443        struct registry_context context;
    4544        struct dcerpc_pipe *pipe;
     45        struct dcerpc_binding_handle *binding_handle;
    4646};
    4747
     
    5252 */
    5353
    54 #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
     54#define openhive(u) static WERROR open_ ## u(struct dcerpc_binding_handle *b, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
    5555{ \
    5656        struct winreg_Open ## u r; \
     
    6262        r.out.handle = hnd;\
    6363\
    64         status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \
     64        status = dcerpc_winreg_Open ## u ## _r(b, mem_ctx, &r); \
    6565\
    6666        if (!NT_STATUS_IS_OK(status)) { \
     
    8282static struct {
    8383        uint32_t hkey;
    84         WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *,
     84        WERROR (*open) (struct dcerpc_binding_handle *b, TALLOC_CTX *,
    8585                        struct policy_handle *h);
    8686} known_hives[] = {
     
    118118
    119119        mykeydata = talloc_zero(ctx, struct rpc_key);
     120        W_ERROR_HAVE_NO_MEMORY(mykeydata);
    120121        mykeydata->key.context = ctx;
    121         mykeydata->pipe = talloc_reference(mykeydata, rctx->pipe);
     122        mykeydata->binding_handle = rctx->binding_handle;
    122123        mykeydata->num_values = -1;
    123124        mykeydata->num_subkeys = -1;
    124125        *k = (struct registry_key *)mykeydata;
    125         return known_hives[n].open(mykeydata->pipe, mykeydata, &(mykeydata->pol));
     126        return known_hives[n].open(mykeydata->binding_handle, mykeydata, &mykeydata->pol);
    126127}
    127128
     
    161162
    162163        mykeydata = talloc_zero(mem_ctx, struct rpc_key);
     164        W_ERROR_HAVE_NO_MEMORY(mykeydata);
    163165        mykeydata->key.context = parentkeydata->key.context;
    164         mykeydata->pipe = talloc_reference(mykeydata, parentkeydata->pipe);
     166        mykeydata->binding_handle = parentkeydata->binding_handle;
    165167        mykeydata->num_values = -1;
    166168        mykeydata->num_subkeys = -1;
     
    171173        r.in.parent_handle = &parentkeydata->pol;
    172174        r.in.keyname.name = name;
    173         r.in.unknown = 0x00000000;
     175        r.in.options = 0x00000000;
    174176        r.in.access_mask = 0x02000000;
    175177        r.out.handle = &mykeydata->pol;
    176178
    177         status = dcerpc_winreg_OpenKey(mykeydata->pipe, mem_ctx, &r);
     179        status = dcerpc_winreg_OpenKey_r(mykeydata->binding_handle, mem_ctx, &r);
    178180
    179181        if (!NT_STATUS_IS_OK(status)) {
     
    213215        r.in.enum_index = n;
    214216        r.in.name = &name;
    215         r.in.type = type;
     217        r.in.type = (enum winreg_Type *) type;
    216218        r.in.value = &value;
    217219        r.in.size = &val_size;
    218220        r.in.length = &zero;
    219221        r.out.name = &name;
    220         r.out.type = type;
     222        r.out.type = (enum winreg_Type *) type;
    221223        r.out.value = &value;
    222224        r.out.size = &val_size;
    223225        r.out.length = &zero;
    224226
    225         status = dcerpc_winreg_EnumValue(mykeydata->pipe, mem_ctx, &r);
     227        status = dcerpc_winreg_EnumValue_r(mykeydata->binding_handle, mem_ctx, &r);
    226228
    227229        if (!NT_STATUS_IS_OK(status)) {
     
    230232        }
    231233
    232         *value_name = talloc_reference(mem_ctx, r.out.name->name);
     234        *value_name = talloc_steal(mem_ctx, r.out.name->name);
    233235        *type = *(r.out.type);
    234236        *data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length);
     
    262264        r.in.handle = &mykeydata->pol;
    263265        r.in.value_name = &name;
    264         r.in.type = type;
     266        r.in.type = (enum winreg_Type *) type;
    265267        r.in.data = &value;
    266268        r.in.data_size = &val_size;
    267269        r.in.data_length = &zero;
    268         r.out.type = type;
     270        r.out.type = (enum winreg_Type *) type;
    269271        r.out.data = &value;
    270272        r.out.data_size = &val_size;
    271273        r.out.data_length = &zero;
    272274
    273         status = dcerpc_winreg_QueryValue(mykeydata->pipe, mem_ctx, &r);
     275        status = dcerpc_winreg_QueryValue_r(mykeydata->binding_handle, mem_ctx, &r);
    274276
    275277        if (!NT_STATUS_IS_OK(status)) {
     
    312314        r.out.last_changed_time = &change_time;
    313315
    314         status = dcerpc_winreg_EnumKey(mykeydata->pipe, mem_ctx, &r);
     316        status = dcerpc_winreg_EnumKey_r(mykeydata->binding_handle, mem_ctx, &r);
    315317
    316318        if (!NT_STATUS_IS_OK(status)) {
     
    320322
    321323        if (name != NULL)
    322                 *name = talloc_reference(mem_ctx, r.out.name->name);
     324                *name = talloc_steal(mem_ctx, r.out.name->name);
    323325        if (keyclass != NULL)
    324                 *keyclass = talloc_reference(mem_ctx, r.out.keyclass->name);
     326                *keyclass = talloc_steal(mem_ctx, r.out.keyclass->name);
    325327        if (last_changed_time != NULL)
    326328                *last_changed_time = *(r.out.last_changed_time);
     
    330332
    331333static WERROR rpc_add_key(TALLOC_CTX *mem_ctx,
    332                           struct registry_key *parent, const char *name,
     334                          struct registry_key *parent, const char *path,
    333335                          const char *key_class,
    334336                          struct security_descriptor *sec,
     
    343345        ZERO_STRUCT(r);
    344346        r.in.handle = &parentkd->pol;
    345         r.in.name.name = name;
     347        r.in.name.name = path;
    346348        r.in.keyclass.name = NULL;
    347349        r.in.options = 0;
     
    352354        r.out.action_taken = NULL;
    353355
    354         status = dcerpc_winreg_CreateKey(parentkd->pipe, mem_ctx, &r);
     356        status = dcerpc_winreg_CreateKey_r(parentkd->binding_handle, mem_ctx, &r);
    355357
    356358        if (!NT_STATUS_IS_OK(status)) {
     
    360362        }
    361363
    362         rpck->pipe = talloc_reference(rpck, parentkd->pipe);
     364        rpck->binding_handle = parentkd->binding_handle;
    363365        *key = (struct registry_key *)rpck;
    364366
     
    388390        r.out.last_changed_time = &mykeydata->last_changed_time;
    389391
    390         status = dcerpc_winreg_QueryInfoKey(mykeydata->pipe, mem_ctx, &r);
     392        status = dcerpc_winreg_QueryInfoKey_r(mykeydata->binding_handle, mem_ctx, &r);
    391393
    392394        if (!NT_STATUS_IS_OK(status)) {
     
    395397        }
    396398
    397         mykeydata->classname = talloc_reference(mem_ctx, r.out.classname->name);
    398 
    399         return r.out.result;
    400 }
    401 
    402 static WERROR rpc_del_key(struct registry_key *parent, const char *name)
     399        mykeydata->classname = talloc_steal(mem_ctx, r.out.classname->name);
     400
     401        return r.out.result;
     402}
     403
     404static WERROR rpc_del_key(TALLOC_CTX *mem_ctx, struct registry_key *parent,
     405                          const char *name)
    403406{
    404407        NTSTATUS status;
    405408        struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
    406409        struct winreg_DeleteKey r;
    407         TALLOC_CTX *mem_ctx = talloc_init("del_key");
    408410
    409411        ZERO_STRUCT(r);
     
    411413        r.in.key.name = name;
    412414
    413         status = dcerpc_winreg_DeleteKey(mykeydata->pipe, mem_ctx, &r);
    414 
    415         talloc_free(mem_ctx);
     415        status = dcerpc_winreg_DeleteKey_r(mykeydata->binding_handle, mem_ctx, &r);
    416416
    417417        if (!NT_STATUS_IS_OK(status)) {
     
    474474        .delete_key = rpc_del_key,
    475475        .get_key_info = rpc_get_info,
    476         .get_predefined_key = rpc_get_predefined_key,
    477476};
    478477
     
    490489
    491490        rctx = talloc(NULL, struct rpc_registry_context);
     491        W_ERROR_HAVE_NO_MEMORY(rctx);
    492492
    493493        /* Default to local smbd if no connection is specified */
     
    498498        status = dcerpc_pipe_connect(rctx /* TALLOC_CTX */,
    499499                                     &p, location,
    500                                         &ndr_table_winreg,
     500                                    &ndr_table_winreg,
    501501                                     credentials, ev, lp_ctx);
    502         rctx->pipe = p;
    503 
    504502        if(NT_STATUS_IS_ERR(status)) {
    505503                DEBUG(1, ("Unable to open '%s': %s\n", location,
     
    510508        }
    511509
     510        rctx->pipe = p;
     511        rctx->binding_handle = p->binding_handle;
     512
    512513        *ctx = (struct registry_context *)rctx;
    513514        (*ctx)->ops = &reg_backend_rpc;
  • trunk/server/source4/lib/registry/samba.c

    r414 r745  
    3939
    4040        location = talloc_asprintf(ctx, "%s/%s.ldb",
    41                                    lp_private_dir(lp_ctx),
     41                                   lpcfg_private_dir(lp_ctx),
    4242                                   name);
     43        W_ERROR_HAVE_NO_MEMORY(location);
    4344
    4445        error = reg_open_hive(ctx, location, auth_info, creds, event_ctx, lp_ctx, &hive);
     
    4748                error = reg_open_ldb_file(ctx, location, auth_info,
    4849                                          creds, event_ctx, lp_ctx, &hive);
     50
     51        talloc_free(discard_const_p(char, location));
    4952
    5053        if (!W_ERROR_IS_OK(error))
  • trunk/server/source4/lib/registry/tests/diff.c

    r414 r745  
    5353{
    5454        struct diff_tcase_data *td = tcase_data;
    55         struct smb_iconv_convenience *ic;
    5655        struct reg_diff_callbacks *callbacks;
    5756        void *data;
    5857        WERROR error;
    5958
    60         ic = lp_iconv_convenience(tctx->lp_ctx);
    61 
    62         error = reg_diff_load(td->filename, iconv_convenience, callbacks, data);
     59        error = reg_diff_load(td->filename, callbacks, data);
    6360        torture_assert_werr_ok(tctx, error, "reg_diff_load");
    6461
     
    7269        WERROR error;
    7370
    74         error = reg_diff_apply(td->r1_ctx, lp_iconv_convenience(tctx->lp_ctx), td->filename);
     71        error = reg_diff_apply(td->r1_ctx, td->filename);
    7572        torture_assert_werr_ok(tctx, error, "reg_diff_apply");
    7673
     
    228225        torture_assert_werr_ok(tctx, error, "Creating HKLM\\..\\Policies\\Explorer failed");
    229226
    230 
    231         blob.data = (void *)talloc(r2_ctx, uint32_t);
    232         SIVAL(blob.data, 0, 0x03ffffff);
    233         blob.length = sizeof(uint32_t);
     227        blob.data = talloc_array(r2_ctx, uint8_t, 4);
     228        /* set "0x03FFFFFF" in little endian format */
     229        blob.data[0] = 0xFF; blob.data[1] = 0xFF;
     230        blob.data[2] = 0xFF; blob.data[3] = 0x03;
     231        blob.length = 4;
    234232
    235233        r1_ctx->ops->set_value(newkey, "NoDrives", REG_DWORD, blob);
     
    247245{
    248246        struct diff_tcase_data *td;
    249         struct smb_iconv_convenience *ic;
    250247        WERROR error;
    251248
     
    253250        td = *data;
    254251
    255         ic = lp_iconv_convenience(tctx->lp_ctx);
    256 
    257252        td->filename = talloc_asprintf(tctx, "%s/test.pol", td->tempdir);
    258         error = reg_preg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data);
     253        error = reg_preg_diff_save(tctx, td->filename,  &td->callbacks,
     254                                                           &td->callback_data);
    259255        torture_assert_werr_ok(tctx, error, "reg_preg_diff_save");
    260256
     
    265261{
    266262        struct diff_tcase_data *td;
    267         struct smb_iconv_convenience *ic;
    268263        WERROR error;
    269264
     
    271266        td = *data;
    272267
    273         ic = lp_iconv_convenience(tctx->lp_ctx);
    274        
    275268        td->filename = talloc_asprintf(tctx, "%s/test.reg", td->tempdir);
    276         error = reg_dotreg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data);
     269        error = reg_dotreg_diff_save(tctx, td->filename, &td->callbacks,
     270                                                                 &td->callback_data);
    277271        torture_assert_werr_ok(tctx, error, "reg_dotreg_diff_save");
    278272
     
    283277{
    284278        struct torture_tcase *tcase;
    285         struct torture_suite *suite = torture_suite_create(mem_ctx, "DIFF");
     279        struct torture_suite *suite = torture_suite_create(mem_ctx, "diff");
    286280
    287281        tcase = torture_suite_add_tcase(suite, "PReg");
  • trunk/server/source4/lib/registry/tests/generic.c

    r414 r745  
    3232static bool test_str_regtype(struct torture_context *ctx)
    3333{
     34        torture_assert_str_equal(ctx, str_regtype(0),
     35                                 "REG_NONE", "REG_NONE failed");
    3436        torture_assert_str_equal(ctx, str_regtype(1),
    3537                                 "REG_SZ", "REG_SZ failed");
     38        torture_assert_str_equal(ctx, str_regtype(2),
     39                                 "REG_EXPAND_SZ", "REG_EXPAND_SZ failed");
     40        torture_assert_str_equal(ctx, str_regtype(3),
     41                                 "REG_BINARY", "REG_BINARY failed");
    3642        torture_assert_str_equal(ctx, str_regtype(4),
    3743                                 "REG_DWORD", "REG_DWORD failed");
     44        torture_assert_str_equal(ctx, str_regtype(5),
     45                                 "REG_DWORD_BIG_ENDIAN", "REG_DWORD_BIG_ENDIAN failed");
     46        torture_assert_str_equal(ctx, str_regtype(6),
     47                                 "REG_LINK", "REG_LINK failed");
     48        torture_assert_str_equal(ctx, str_regtype(7),
     49                                 "REG_MULTI_SZ", "REG_MULTI_SZ failed");
     50        torture_assert_str_equal(ctx, str_regtype(8),
     51                                 "REG_RESOURCE_LIST", "REG_RESOURCE_LIST failed");
     52        torture_assert_str_equal(ctx, str_regtype(9),
     53                                 "REG_FULL_RESOURCE_DESCRIPTOR", "REG_FULL_RESOURCE_DESCRIPTOR failed");
     54        torture_assert_str_equal(ctx, str_regtype(10),
     55                                 "REG_RESOURCE_REQUIREMENTS_LIST", "REG_RESOURCE_REQUIREMENTS_LIST failed");
     56        torture_assert_str_equal(ctx, str_regtype(11),
     57                                 "REG_QWORD", "REG_QWORD failed");
    3858
    3959        return true;
     
    4363static bool test_reg_val_data_string_dword(struct torture_context *ctx)
    4464{
    45         uint32_t d = 0x20;
    46         DATA_BLOB db = { (uint8_t *)&d, sizeof(d) };
    47         torture_assert_str_equal(ctx, "0x20",
    48                                  reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx), REG_DWORD, db),
     65        uint8_t d[] = { 0x20, 0x00, 0x00, 0x00 };
     66        DATA_BLOB db = { d, 4 };
     67        torture_assert_str_equal(ctx, "0x00000020",
     68                                 reg_val_data_string(ctx, REG_DWORD, db),
    4969                                 "dword failed");
     70        return true;
     71}
     72
     73static bool test_reg_val_data_string_dword_big_endian(struct torture_context *ctx)
     74{
     75        uint8_t d[] = { 0x20, 0x00, 0x00, 0x00 };
     76        DATA_BLOB db = { d, 4 };
     77        torture_assert_str_equal(ctx, "0x00000020",
     78                                 reg_val_data_string(ctx, REG_DWORD_BIG_ENDIAN, db),
     79                                 "dword failed");
     80        return true;
     81}
     82
     83static bool test_reg_val_data_string_qword(struct torture_context *ctx)
     84{
     85        uint8_t d[] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
     86        DATA_BLOB db = { d, 8 };
     87        torture_assert_str_equal(ctx, "0x0000000000000020",
     88                                 reg_val_data_string(ctx, REG_QWORD, db),
     89                                 "qword failed");
    5090        return true;
    5191}
     
    5494{
    5595        DATA_BLOB db;
    56         convert_string_talloc_convenience(ctx, lp_iconv_convenience(ctx->lp_ctx), CH_UTF8, CH_UTF16,
     96        convert_string_talloc(ctx, CH_UTF8, CH_UTF16,
    5797                                          "bla", 3, (void **)&db.data, &db.length, false);
    5898        torture_assert_str_equal(ctx, "bla",
    59                                  reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx), REG_SZ, db),
     99                                 reg_val_data_string(ctx, REG_SZ, db),
    60100                                 "sz failed");
    61101        db.length = 4;
    62102        torture_assert_str_equal(ctx, "bl",
    63                                  reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx), REG_SZ, db),
     103                                 reg_val_data_string(ctx, REG_SZ, db),
    64104                                 "sz failed");
    65105        return true;
     
    71111        DATA_BLOB db = { x, 4 };
    72112        torture_assert_str_equal(ctx, "01020304",
    73                                  reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx), REG_BINARY, db),
     113                                 reg_val_data_string(ctx, REG_BINARY, db),
    74114                                 "binary failed");
    75115        return true;
     
    81121        DATA_BLOB db = { NULL, 0 };
    82122        torture_assert_str_equal(ctx, "",
    83                                  reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx), REG_BINARY, db),
     123                                 reg_val_data_string(ctx, REG_BINARY, db),
    84124                                 "empty failed");
    85125        return true;
     
    89129{
    90130        DATA_BLOB data;
    91         convert_string_talloc_convenience(ctx, lp_iconv_convenience(ctx->lp_ctx), CH_UTF8, CH_UTF16,
     131        convert_string_talloc(ctx, CH_UTF8, CH_UTF16,
    92132                                            "stationary traveller",
    93133                                            strlen("stationary traveller"),
    94134                                            (void **)&data.data, &data.length, false);
    95135        torture_assert_str_equal(ctx, "camel = REG_SZ : stationary traveller",
    96                                  reg_val_description(ctx, lp_iconv_convenience(ctx->lp_ctx), "camel", REG_SZ, data),
     136                                 reg_val_description(ctx, "camel", REG_SZ, data),
    97137                                 "reg_val_description failed");
    98138        return true;
     
    103143{
    104144        DATA_BLOB data;
    105         convert_string_talloc_convenience(ctx, lp_iconv_convenience(ctx->lp_ctx), CH_UTF8, CH_UTF16,
     145        convert_string_talloc(ctx, CH_UTF8, CH_UTF16,
    106146                                            "west berlin",
    107147                                            strlen("west berlin"),
    108148                                            (void **)&data.data, &data.length, false);
    109149        torture_assert_str_equal(ctx, "<No Name> = REG_SZ : west berlin",
    110                                  reg_val_description(ctx, lp_iconv_convenience(ctx->lp_ctx), NULL, REG_SZ, data),
     150                                 reg_val_description(ctx, NULL, REG_SZ, data),
    111151                                 "description with null name failed");
    112152        return true;
     
    115155struct torture_suite *torture_registry(TALLOC_CTX *mem_ctx)
    116156{
    117         struct torture_suite *suite = torture_suite_create(mem_ctx, "REGISTRY");
     157        struct torture_suite *suite = torture_suite_create(mem_ctx, "registry");
    118158        torture_suite_add_simple_test(suite, "str_regtype",
    119159                                      test_str_regtype);
    120160        torture_suite_add_simple_test(suite, "reg_val_data_string dword",
    121161                                      test_reg_val_data_string_dword);
     162        torture_suite_add_simple_test(suite, "reg_val_data_string dword_big_endian",
     163                                      test_reg_val_data_string_dword_big_endian);
     164        torture_suite_add_simple_test(suite, "reg_val_data_string qword",
     165                                      test_reg_val_data_string_qword);
    122166        torture_suite_add_simple_test(suite, "reg_val_data_string sz",
    123167                                      test_reg_val_data_string_sz);
  • trunk/server/source4/lib/registry/tests/hive.c

    r414 r745  
    3333{
    3434        const struct hive_key *root = (const struct hive_key *)test_data;
    35         WERROR error = hive_key_del(root, "bla");
     35        WERROR error = hive_key_del(tctx, root, "bla");
    3636        torture_assert_werr_equal(tctx, error, WERR_BADFILE,
    3737                                  "invalid return code");
     
    7070        WERROR error;
    7171        struct hive_key *subkey;
    72         char data[4];
    73         SIVAL(data, 0, 42);
     72        uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 };
     73        DATA_BLOB db = { d, 4 };
    7474
    7575        error = hive_key_add_name(tctx, root, "Nested Keyll", NULL,
     
    7777        torture_assert_werr_ok(tctx, error, "hive_key_add_name");
    7878
    79         error = hive_key_set_value(root, "Answer", REG_DWORD,
    80                                data_blob_talloc(tctx, data, sizeof(data)));
     79        error = hive_key_set_value(root, "Answer", REG_DWORD, db);
    8180        torture_assert_werr_ok(tctx, error, "hive_key_set_value");
    8281
     
    108107        torture_assert_werr_ok(tctx, error, "hive_key_add_name");
    109108
    110         error = hive_key_del(root, "Nested Key");
     109        error = hive_key_del(mem_ctx, root, "Nested Key");
    111110        torture_assert_werr_ok(tctx, error, "reg_key_del");
    112111
     
    122121        const struct hive_key *root = (const struct hive_key *)test_data;
    123122        TALLOC_CTX *mem_ctx = tctx;
    124         char data[4];
    125         SIVAL(data, 0, 42);
     123        uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 };
     124        DATA_BLOB db = { d, 4 };
    126125
    127126        /* Create a new key under the root */
     
    136135
    137136        /* Create a new value under "Child Key" */
    138         error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD,
    139                                data_blob_talloc(mem_ctx, data, sizeof(data)));
     137        error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD, db);
    140138        torture_assert_werr_ok(tctx, error, "hive_key_set_value");
    141139
    142140        /* Deleting "Parent Key" will also delete "Child Key" and the value. */
    143         error = hive_key_del(root, "Parent Key");
     141        error = hive_key_del(mem_ctx, root, "Parent Key");
    144142        torture_assert_werr_ok(tctx, error, "hive_key_del");
    145143
     
    167165        torture_assert_werr_ok(tctx, error, "hive_key_add_name");
    168166
    169         error = hive_key_del(root, "Nested Key");
     167        error = hive_key_del(mem_ctx, root, "Nested Key");
    170168        torture_assert_werr_ok(tctx, error, "reg_key_del");
    171169
    172         error = hive_key_del(root, "Nested Key");
     170        error = hive_key_del(mem_ctx, root, "Nested Key");
    173171        torture_assert_werr_equal(tctx, error, WERR_BADFILE, "reg_key_del");
    174172
     
    183181        const struct hive_key *root = (const struct hive_key *)test_data;
    184182        TALLOC_CTX *mem_ctx = tctx;
    185         char data[4];
    186         SIVAL(data, 0, 42);
     183        uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 };
     184        DATA_BLOB db = { d, 4 };
    187185
    188186        error = hive_key_add_name(mem_ctx, root, "YA Nested Key", NULL,
     
    190188        torture_assert_werr_ok(tctx, error, "hive_key_add_name");
    191189
    192         error = hive_key_set_value(subkey, "Answer", REG_DWORD,
    193                                data_blob_talloc(mem_ctx, data, sizeof(data)));
     190        error = hive_key_set_value(subkey, "Answer", REG_DWORD, db);
    194191        torture_assert_werr_ok(tctx, error, "hive_key_set_value");
    195192
     
    203200        const struct hive_key *root = (const struct hive_key *)test_data;
    204201        TALLOC_CTX *mem_ctx = tctx;
    205         char data[4];
    206202        uint32_t type;
    207         DATA_BLOB value;
    208 
    209         SIVAL(data, 0, 42);
     203        uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 };
     204        DATA_BLOB db = { d, 4 }, data;
    210205
    211206        error = hive_key_add_name(mem_ctx, root, "EYA Nested Key", NULL,
     
    213208        torture_assert_werr_ok(tctx, error, "hive_key_add_name");
    214209
    215         error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
     210        error = hive_get_value(mem_ctx, subkey, "Answer", &type, &data);
    216211        torture_assert_werr_equal(tctx, error, WERR_BADFILE,
    217212                                  "getting missing value");
    218213
    219         error = hive_key_set_value(subkey, "Answer", REG_DWORD,
    220                                data_blob_talloc(mem_ctx, data, sizeof(data)));
    221         torture_assert_werr_ok(tctx, error, "hive_key_set_value");
    222 
    223         error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
     214        error = hive_key_set_value(subkey, "Answer", REG_DWORD, db);
     215        torture_assert_werr_ok(tctx, error, "hive_key_set_value");
     216
     217        error = hive_get_value(mem_ctx, subkey, "Answer", &type, &data);
    224218        torture_assert_werr_ok(tctx, error, "getting value");
    225219
    226         torture_assert_int_equal(tctx, value.length, 4, "value length");
     220        torture_assert_int_equal(tctx, data.length, 4, "value length");
    227221        torture_assert_int_equal(tctx, type, REG_DWORD, "value type");
    228222
    229         torture_assert_mem_equal(tctx, &data, value.data, sizeof(uint32_t),
    230                                  "value data");
     223        torture_assert_mem_equal(tctx, data.data, db.data, 4, "value data");
    231224
    232225        return true;
     
    239232        const struct hive_key *root = (const struct hive_key *)test_data;
    240233        TALLOC_CTX *mem_ctx = tctx;
    241         char data[4];
    242234        uint32_t type;
    243         DATA_BLOB value;
    244 
    245         SIVAL(data, 0, 42);
     235        uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 };
     236        DATA_BLOB db = { d, 4 };
    246237
    247238        error = hive_key_add_name(mem_ctx, root, "EEYA Nested Key", NULL,
     
    249240        torture_assert_werr_ok(tctx, error, "hive_key_add_name");
    250241
    251         error = hive_key_set_value(subkey, "Answer", REG_DWORD,
    252                                data_blob_talloc(mem_ctx, data, sizeof(data)));
    253         torture_assert_werr_ok(tctx, error, "hive_key_set_value");
    254 
    255         error = hive_key_del_value(subkey, "Answer");
     242        error = hive_key_set_value(subkey, "Answer", REG_DWORD, db);
     243        torture_assert_werr_ok(tctx, error, "hive_key_set_value");
     244
     245        error = hive_key_del_value(mem_ctx, subkey, "Answer");
    256246        torture_assert_werr_ok(tctx, error, "deleting value");
    257247
    258         error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
     248        error = hive_get_value(mem_ctx, subkey, "Answer", &type, &db);
    259249        torture_assert_werr_equal(tctx, error, WERR_BADFILE, "getting value");
    260250
    261         error = hive_key_del_value(subkey, "Answer");
     251        error = hive_key_del_value(mem_ctx, subkey, "Answer");
    262252        torture_assert_werr_equal(tctx, error, WERR_BADFILE,
    263253                                  "deleting value");
     
    273263        const struct hive_key *root = (const struct hive_key *)test_data;
    274264        TALLOC_CTX *mem_ctx = tctx;
    275         char data[4];
    276265        uint32_t type;
    277         DATA_BLOB value;
     266        uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 };
     267        DATA_BLOB db = { d, 4 }, data;
    278268        const char *name;
    279         int data_val = 42;
    280         SIVAL(data, 0, data_val);
    281269
    282270        error = hive_key_add_name(mem_ctx, root, "AYAYA Nested Key", NULL,
     
    284272        torture_assert_werr_ok(tctx, error, "hive_key_add_name");
    285273
    286         error = hive_key_set_value(subkey, "Answer", REG_DWORD,
    287                                data_blob_talloc(mem_ctx, data, sizeof(data)));
     274        error = hive_key_set_value(subkey, "Answer", REG_DWORD, db);
    288275        torture_assert_werr_ok(tctx, error, "hive_key_set_value");
    289276
    290277        error = hive_get_value_by_index(mem_ctx, subkey, 0, &name,
    291                                         &type, &value);
     278                                        &type, &data);
    292279        torture_assert_werr_ok(tctx, error, "getting value");
    293280
    294281        torture_assert_str_equal(tctx, name, "Answer", "value name");
    295282
    296         torture_assert_int_equal(tctx, value.length, 4, "value length");
     283        torture_assert_int_equal(tctx, data.length, 4, "value length");
    297284        torture_assert_int_equal(tctx, type, REG_DWORD, "value type");
    298285       
     286        torture_assert_mem_equal(tctx, data.data, db.data, 4, "value data");
    299287       
    300         torture_assert_int_equal(tctx, data_val, IVAL(value.data, 0), "value data");
    301 
    302288        error = hive_get_value_by_index(mem_ctx, subkey, 1, &name,
    303                                         &type, &value);
     289                                        &type, &data);
    304290        torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
    305291                                  "getting missing value");
     
    450436        rmdir(dirname);
    451437
    452         error = reg_create_regf_file(tctx, lp_iconv_convenience(tctx->lp_ctx),
    453                                      dirname, 5, &key);
     438        error = reg_create_regf_file(tctx, dirname, 5, &key);
    454439        if (!W_ERROR_IS_OK(error)) {
    455440                fprintf(stderr, "Unable to create new regf file\n");
     
    473458{
    474459        struct torture_tcase *tcase;
    475         struct torture_suite *suite = torture_suite_create(mem_ctx, "HIVE");
     460        struct torture_suite *suite = torture_suite_create(mem_ctx, "hive");
    476461
    477462        torture_suite_add_simple_test(suite, "dir-refuses-null-location",
  • trunk/server/source4/lib/registry/tests/registry.c

    r414 r745  
    118118{
    119119        struct registry_context *rctx = (struct registry_context *)_data;
    120         struct registry_key *root, *newkey1, *newkey2;
     120        struct registry_key *root, *newkey;
    121121        WERROR error;
    122122
     
    125125                               "getting predefined key failed");
    126126
    127         error = reg_key_add_name(rctx, root, "Hamburg", NULL, NULL,
    128                                  &newkey1);
     127        error = reg_key_add_name(rctx, root, "Hamburg\\Hamburg", NULL, NULL,
     128                                 &newkey);
    129129        torture_assert_werr_ok(tctx, error, "Creating key return code");
    130         torture_assert(tctx, newkey1 != NULL, "Creating new key");
    131 
    132         error = reg_key_add_name(rctx, root, "Hamburg\\Hamburg", NULL, NULL,
    133                                  &newkey2);
    134         torture_assert_werr_ok(tctx, error, "Creating key return code");
    135         torture_assert(tctx, newkey2 != NULL, "Creating new key");
     130        torture_assert(tctx, newkey != NULL, "Creating new key");
    136131
    137132        return true;
     
    201196        torture_assert(tctx, newkey != NULL, "Creating new key");
    202197
    203         error = reg_key_del(root, "Polen");
     198        error = reg_key_del(tctx, root, "Polen");
    204199        torture_assert_werr_ok(tctx, error, "Delete key");
    205200
    206         error = reg_key_del(root, "Polen");
     201        error = reg_key_del(tctx, root, "Polen");
    207202        torture_assert_werr_equal(tctx, error, WERR_BADFILE,
    208203                                  "Delete missing key");
     
    465460        torture_assert_werr_ok (tctx, error, "setting value");
    466461
    467         error = reg_del_value(subkey, __FUNCTION__);
     462        error = reg_del_value(tctx, subkey, __FUNCTION__);
    468463        torture_assert_werr_ok (tctx, error, "unsetting value");
    469464
     
    585580{
    586581        struct torture_tcase *tcase;
    587         struct torture_suite *suite = torture_suite_create(mem_ctx, "REGISTRY");
     582        struct torture_suite *suite = torture_suite_create(mem_ctx, "registry");
    588583
    589584        tcase = torture_suite_add_tcase(suite, "local");
  • trunk/server/source4/lib/registry/tools/regdiff.c

    r414 r745  
    131131        poptFreeContext(pc);
    132132
    133         error = reg_dotreg_diff_save(ctx, outputfile, lp_iconv_convenience(cmdline_lp_ctx), &callbacks,
    134                                      &callback_data);
     133        error = reg_dotreg_diff_save(ctx, outputfile, &callbacks, &callback_data);
    135134        if (!W_ERROR_IS_OK(error)) {
    136135                fprintf(stderr, "Problem saving registry diff to '%s': %s\n",
  • trunk/server/source4/lib/registry/tools/regpatch.c

    r414 r745  
    6969        poptFreeContext(pc);
    7070
    71         reg_diff_apply(h, lp_iconv_convenience(cmdline_lp_ctx), patch);
     71        reg_diff_apply(h, patch);
    7272
    7373        return 0;
  • trunk/server/source4/lib/registry/tools/regshell.c

    r414 r745  
    2525#include "lib/events/events.h"
    2626#include "system/time.h"
    27 #include "lib/smbreadline/smbreadline.h"
     27#include "../libcli/smbreadline/smbreadline.h"
    2828#include "librpc/gen_ndr/ndr_security.h"
    2929#include "lib/registry/tools/common.h"
     
    126126                printf("Key Class: %s\n", classname);
    127127        last_mod = nt_time_to_unix(last_change);
    128         printf("Time Last Modified: %s\n", ctime(&last_mod));
     128        printf("Time Last Modified: %s", ctime(&last_mod));
    129129        printf("Number of subkeys: %d\n", num_subkeys);
    130130        printf("Number of values: %d\n", num_values);
     
    141141        error = reg_get_sec_desc(ctx, ctx->current, &sec_desc);
    142142        if (!W_ERROR_IS_OK(error)) {
    143                 printf("Error getting security descriptor\n");
    144                 return error;
     143                printf("Error getting security descriptor: %s\n", win_errstr(error));
     144                return WERR_OK;
    145145        }
    146146        ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor,
     
    196196        }
    197197
    198         if (!reg_string_to_val(ctx, lp_iconv_convenience(cmdline_lp_ctx),
    199                                argv[2], argv[3], &val.data_type,
    200                                &val.data)) {
     198        if (!reg_string_to_val(ctx, argv[2], argv[3], &val.data_type, &val.data)) {
    201199                fprintf(stderr, "Unable to interpret data\n");
    202200                return WERR_INVALID_PARAM;
     
    260258
    261259        printf("%s\n%s\n", str_regtype(value_type),
    262                    reg_val_data_string(ctx, lp_iconv_convenience(cmdline_lp_ctx), value_type, value_data));
     260                   reg_val_data_string(ctx, value_type, value_data));
    263261
    264262        return WERR_OK;
     
    267265static WERROR cmd_ls(struct regshell_context *ctx, int argc, char **argv)
    268266{
    269         int i;
     267        unsigned int i;
    270268        WERROR error;
    271269        uint32_t valuetype;
     
    283281
    284282        if (!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
    285                 fprintf(stderr, "Error occured while browsing thru keys: %s\n",
     283                fprintf(stderr, "Error occurred while browsing through keys: %s\n",
    286284                        win_errstr(error));
    287285                return error;
     
    291289                ctx->current, i, &name, &valuetype, &valuedata)); i++)
    292290                printf("V \"%s\" %s %s\n", name, str_regtype(valuetype),
    293                            reg_val_data_string(ctx, lp_iconv_convenience(cmdline_lp_ctx), valuetype, valuedata));
     291                           reg_val_data_string(ctx, valuetype, valuedata));
    294292
    295293        return WERR_OK;
     
    326324        }
    327325
    328         error = reg_key_del(ctx->current, argv[1]);
     326        error = reg_key_del(ctx, ctx->current, argv[1]);
    329327        if(!W_ERROR_IS_OK(error)) {
    330328                fprintf(stderr, "Error deleting '%s'\n", argv[1]);
     
    346344        }
    347345
    348         error = reg_del_value(ctx->current, argv[1]);
     346        error = reg_del_value(ctx, ctx->current, argv[1]);
    349347        if(!W_ERROR_IS_OK(error)) {
    350348                fprintf(stderr, "Error deleting value '%s'\n", argv[1]);
     
    389387                       int argc, char **argv)
    390388{
    391         int i;
     389        unsigned int i;
    392390        printf("Available commands:\n");
    393391        for(i = 0; regshell_cmds[i].name; i++) {
     
    430428        /* Complete command */
    431429        char **matches;
    432         int i, len, samelen=0, count=1;
     430        size_t len, samelen=0;
     431        unsigned int i, count=1;
    433432
    434433        matches = malloc_array_p(char *, MAX_COMPLETIONS);
     
    478477        struct registry_key *base;
    479478        const char *subkeyname;
    480         int i, j = 1;
    481         int samelen = 0;
    482         int len;
     479        unsigned int i, j = 1;
     480        size_t len, samelen = 0;
    483481        char **matches;
    484482        const char *base_n = "";
     
    594592
    595593        if (ctx->current == NULL) {
    596                 int i;
     594                unsigned int i;
    597595
    598596                for (i = 0; (reg_predefined_keys[i].handle != 0) &&
     
    617615        if (ctx->current == NULL) {
    618616                fprintf(stderr, "Unable to access any of the predefined keys\n");
    619                 return -1;
     617                return 1;
    620618        }
    621619
     
    625623                char *line, *prompt;
    626624
    627                 asprintf(&prompt, "%s\\%s> ", ctx->predef?ctx->predef:"", ctx->path);
     625                if (asprintf(&prompt, "%s\\%s> ", ctx->predef?ctx->predef:"",
     626                             ctx->path) < 0) {
     627                        ret = false;
     628                        break;
     629                }
    628630
    629631                current_key = ctx->current;             /* No way to pass a void * pointer
  • trunk/server/source4/lib/registry/tools/regtree.c

    r414 r745  
    3434 * @param novals Whether values should not be printed
    3535 */
    36 static void print_tree(int level, struct registry_key *p,
     36static void print_tree(unsigned int level, struct registry_key *p,
    3737                       const char *name,
    3838                       bool fullpath, bool novals)
     
    4444        struct security_descriptor *sec_desc;
    4545        WERROR error;
    46         int i;
     46        unsigned int i;
    4747        TALLOC_CTX *mem_ctx;
    4848
     
    7070
    7171        if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
    72                 DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n",
     72                DEBUG(0, ("Error occurred while fetching subkeys for '%s': %s\n",
    7373                                  name, win_errstr(error)));
    7474        }
     
    7979                        mem_ctx, p, i, &valuename, &valuetype, &valuedata));
    8080                        i++) {
    81                         int j;
     81                        unsigned int j;
    8282                        for(j = 0; j < level+1; j++) putchar(' ');
    8383                        printf("%s\n",  reg_val_description(mem_ctx,
    84                                 lp_iconv_convenience(cmdline_lp_ctx), valuename,
    85                                 valuetype, valuedata));
     84                                valuename, valuetype, valuedata));
    8685                }
    8786                talloc_free(mem_ctx);
    8887
    8988                if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
    90                         DEBUG(0, ("Error occured while fetching values for '%s': %s\n",
     89                        DEBUG(0, ("Error occurred while fetching values for '%s': %s\n",
    9190                                name, win_errstr(error)));
    9291                }
     
    102101int main(int argc, char **argv)
    103102{
    104         int opt, i;
     103        int opt;
     104        unsigned int i;
    105105        const char *file = NULL;
    106106        const char *remote = NULL;
  • trunk/server/source4/lib/registry/util.c

    r414 r745  
    33   Transparent registry backend handling
    44   Copyright (C) Jelmer Vernooij                        2003-2007.
     5   Copyright (C) Wilco Baan Hofman                      2010.
    56
    67   This program is free software; you can redistribute it and/or modify
     
    2122#include "lib/registry/registry.h"
    2223#include "librpc/gen_ndr/winreg.h"
    23 
    24 /**
    25  * @file
    26  * @brief Registry utility functions
    27  */
    28 
    29 static const struct {
    30         uint32_t id;
    31         const char *name;
    32 } reg_value_types[] = {
    33         { REG_SZ, "REG_SZ" },
    34         { REG_DWORD, "REG_DWORD" },
    35         { REG_BINARY, "REG_BINARY" },
    36         { REG_EXPAND_SZ, "REG_EXPAND_SZ" },
    37         { REG_NONE, "REG_NONE" },
    38         { 0, NULL }
    39 };
    40 
    41 /** Return string description of registry value type */
    42 _PUBLIC_ const char *str_regtype(int type)
    43 {
    44         int i;
    45         for (i = 0; reg_value_types[i].name; i++) {
    46                 if (reg_value_types[i].id == type)
    47                         return reg_value_types[i].name;
    48         }
    49 
    50         return "Unknown";
    51 }
    52 
    53 _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx,
    54                                    struct smb_iconv_convenience *iconv_convenience,
    55                                    uint32_t type,
     24#include "lib/util/data_blob.h"
     25
     26_PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type,
    5627                                   const DATA_BLOB data)
    5728{
     
    6435                case REG_EXPAND_SZ:
    6536                case REG_SZ:
    66                         convert_string_talloc_convenience(mem_ctx, iconv_convenience, CH_UTF16, CH_UNIX,
     37                        convert_string_talloc(mem_ctx,
     38                                              CH_UTF16, CH_UNIX,
    6739                                              data.data, data.length,
    6840                                              (void **)&ret, NULL, false);
    69                         return ret;
     41                        break;
     42                case REG_DWORD:
     43                case REG_DWORD_BIG_ENDIAN:
     44                        SMB_ASSERT(data.length == sizeof(uint32_t));
     45                        ret = talloc_asprintf(mem_ctx, "0x%8.8x",
     46                                              IVAL(data.data, 0));
     47                        break;
     48                case REG_QWORD:
     49                        SMB_ASSERT(data.length == sizeof(uint64_t));
     50                        ret = talloc_asprintf(mem_ctx, "0x%16.16llx",
     51                                              (long long)BVAL(data.data, 0));
     52                        break;
    7053                case REG_BINARY:
    71                         ret = data_blob_hex_string(mem_ctx, &data);
    72                         return ret;
    73                 case REG_DWORD:
    74                         if (*(int *)data.data == 0)
    75                                 return talloc_strdup(mem_ctx, "0");
    76                         return talloc_asprintf(mem_ctx, "0x%x",
    77                                                *(int *)data.data);
     54                        ret = data_blob_hex_string_upper(mem_ctx, &data);
     55                        break;
     56                case REG_NONE:
     57                        /* "NULL" is the right return value */
     58                        break;
    7859                case REG_MULTI_SZ:
     60                        /* FIXME: We don't support this yet */
     61                        break;
     62                default:
    7963                        /* FIXME */
    80                         break;
    81                 default:
     64                        /* Other datatypes aren't supported -> return "NULL" */
    8265                        break;
    8366        }
     
    8770
    8871/** Generate a string that describes a registry value */
    89 _PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx,
    90                                    struct smb_iconv_convenience *iconv_convenience,
     72_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx,
    9173                                   const char *name,
    9274                                   uint32_t data_type,
     
    9577        return talloc_asprintf(mem_ctx, "%s = %s : %s", name?name:"<No Name>",
    9678                               str_regtype(data_type),
    97                                reg_val_data_string(mem_ctx, iconv_convenience, data_type, data));
    98 }
    99 
    100 _PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx,
    101                                 struct smb_iconv_convenience *iconv_convenience,
    102                                 const char *type_str,
    103                                 const char *data_str, uint32_t *type,
    104                                 DATA_BLOB *data)
    105 {
    106         int i;
    107         *type = -1;
    108 
    109         /* Find the correct type */
    110         for (i = 0; reg_value_types[i].name; i++) {
    111                 if (!strcmp(reg_value_types[i].name, type_str)) {
    112                         *type = reg_value_types[i].id;
    113                         break;
     79                               reg_val_data_string(mem_ctx, data_type, data));
     80}
     81
     82/*
     83 * This implements reading hex bytes that include comma's.
     84 * It was previously handled by strhex_to_data_blob, but that did not cover
     85 * the format used by windows.
     86 */
     87static DATA_BLOB reg_strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *str)
     88{
     89        DATA_BLOB ret;
     90        const char *HEXCHARS = "0123456789ABCDEF";
     91        size_t i, j;
     92        char *hi, *lo;
     93
     94        ret = data_blob_talloc_zero(mem_ctx, (strlen(str)+(strlen(str) % 3))/3);
     95        j = 0;
     96        for (i = 0; i < strlen(str); i++) {
     97                hi = strchr(HEXCHARS, toupper(str[i]));
     98                if (hi == NULL)
     99                        continue;
     100
     101                i++;
     102                lo = strchr(HEXCHARS, toupper(str[i]));
     103                if (lo == NULL)
     104                        break;
     105
     106                ret.data[j] = PTR_DIFF(hi, HEXCHARS) << 4;
     107                ret.data[j] += PTR_DIFF(lo, HEXCHARS);
     108                j++;
     109
     110                if (j > ret.length) {
     111                        DEBUG(0, ("Trouble converting hex string to bin\n"));
     112                        break;
     113                }
     114        }
     115        return ret;
     116}
     117
     118
     119_PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str,
     120                                const char *data_str, uint32_t *type, DATA_BLOB *data)
     121{
     122        char *tmp_type_str, *p, *q;
     123        int result;
     124
     125        *type = regtype_by_string(type_str);
     126
     127        if (*type == -1) {
     128                /* Normal windows format is hex, hex(type int as string),
     129                   dword or just a string. */
     130                if (strncmp(type_str, "hex(", 4) == 0) {
     131                        /* there is a hex string with the value type between
     132                           the braces */
     133                        tmp_type_str = talloc_strdup(mem_ctx, type_str);
     134                        q = p = tmp_type_str + strlen("hex(");
     135
     136                        /* Go to the closing brace or end of the string */
     137                        while (*q != ')' && *q != '\0') q++;
     138                        *q = '\0';
     139
     140                        /* Convert hex string to int, store it in type */
     141                        result = sscanf(p, "%x", type);
     142                        if (!result) {
     143                                DEBUG(0, ("Could not convert hex to int\n"));
     144                                return false;
     145                        }
     146                        talloc_free(tmp_type_str);
     147                } else if (strcmp(type_str, "hex") == 0) {
     148                        *type = REG_BINARY;
     149                } else if (strcmp(type_str, "dword") == 0) {
     150                        *type = REG_DWORD;
    114151                }
    115152        }
     
    120157        /* Convert data appropriately */
    121158
    122         switch (*type)
    123         {
     159        switch (*type) {
    124160                case REG_SZ:
     161                        return convert_string_talloc(mem_ctx,
     162                                                     CH_UNIX, CH_UTF16,
     163                                                     data_str, strlen(data_str)+1,
     164                                                     (void **)&data->data,
     165                                                     &data->length, false);
     166                        break;
     167                case REG_MULTI_SZ:
    125168                case REG_EXPAND_SZ:
    126                 convert_string_talloc_convenience(mem_ctx, iconv_convenience, CH_UNIX, CH_UTF16,
    127                                                      data_str, strlen(data_str),
    128                                                      (void **)&data->data, &data->length, false);
    129                         break;
    130 
    131                 case REG_DWORD: {
    132                         uint32_t tmp = strtol(data_str, NULL, 0);
    133                         *data = data_blob_talloc(mem_ctx, &tmp, 4);
     169                case REG_BINARY:
     170                        *data = reg_strhex_to_data_blob(mem_ctx, data_str);
     171                        break;
     172                case REG_DWORD:
     173                case REG_DWORD_BIG_ENDIAN: {
     174                        uint32_t tmp = strtol(data_str, NULL, 16);
     175                        *data = data_blob_talloc(mem_ctx, NULL, sizeof(uint32_t));
     176                        if (data->data == NULL) return false;
     177                        SIVAL(data->data, 0, tmp);
    134178                        }
    135179                        break;
    136 
     180                case REG_QWORD: {
     181                        uint64_t tmp = strtoll(data_str, NULL, 16);
     182                        *data = data_blob_talloc(mem_ctx, NULL, sizeof(uint64_t));
     183                        if (data->data == NULL) return false;
     184                        SBVAL(data->data, 0, tmp);
     185                        }
     186                        break;
    137187                case REG_NONE:
    138188                        ZERO_STRUCTP(data);
    139189                        break;
    140 
    141                 case REG_BINARY:
    142                         *data = strhex_to_data_blob(mem_ctx, data_str);
    143                         break;
    144 
    145190                default:
    146191                        /* FIXME */
     192                        /* Other datatypes aren't supported -> return no success */
    147193                        return false;
    148194        }
     
    156202        struct registry_key *predef;
    157203        WERROR error;
    158         int predeflength;
     204        size_t predeflength;
    159205        char *predefname;
    160206
     
    165211
    166212        predefname = talloc_strndup(mem_ctx, name, predeflength);
     213        W_ERROR_HAVE_NO_MEMORY(predefname);
    167214        error = reg_get_predefined_key_by_name(handle, predefname, &predef);
    168215        talloc_free(predefname);
     
    193240
    194241        parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-path);
    195 
     242        W_ERROR_HAVE_NO_MEMORY(parent_name);
    196243        error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent);
     244        talloc_free(parent_name);
    197245        if (!W_ERROR_IS_OK(error)) {
    198246                return error;
     
    200248
    201249        *name = talloc_strdup(mem_ctx, strrchr(path, '\\')+1);
     250        W_ERROR_HAVE_NO_MEMORY(*name);
    202251
    203252        return WERR_OK;
     
    217266        error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
    218267        if (W_ERROR_IS_OK(error)) {
    219                 error = reg_key_del(parent, n);
     268                error = reg_key_del(mem_ctx, parent, n);
    220269        }
    221270
     
    233282        const char *n;
    234283        WERROR error;
     284
     285        *result = NULL;
    235286
    236287        if (!strchr(path, '\\')) {
  • trunk/server/source4/lib/socket/access.c

    r414 r745  
    3535#include "lib/socket/socket.h"
    3636#include "system/locale.h"
     37#include "lib/util/util_net.h"
    3738
    3839#define FAIL            (-1)
  • trunk/server/source4/lib/socket/connect_multi.c

    r414 r745  
    3434*/
    3535struct connect_multi_state {
    36         const char *server_address;
     36        struct socket_address *server_address;
    3737        int num_ports;
    3838        uint16_t *ports;
     
    6565_PUBLIC_ struct composite_context *socket_connect_multi_send(
    6666                                                    TALLOC_CTX *mem_ctx,
    67                                                     const char *server_address,
     67                                                    const char *server_name,
    6868                                                    int num_server_ports,
    6969                                                    uint16_t *server_ports,
     
    7575        int i;
    7676
     77        struct nbt_name name;
     78        struct composite_context *creq;
     79               
    7780        result = talloc_zero(mem_ctx, struct composite_context);
    7881        if (result == NULL) return NULL;
     
    8487        result->private_data = multi;
    8588
    86         multi->server_address = talloc_strdup(multi, server_address);
    87         if (composite_nomem(multi->server_address, result)) goto failed;
    88 
    8989        multi->num_ports = num_server_ports;
    9090        multi->ports = talloc_array(multi, uint16_t, multi->num_ports);
     
    9595        }
    9696
    97         if (!is_ipaddress(server_address)) {
    98                 /* 
    99                     we don't want to do the name resolution separately
     97        /* 
     98            we don't want to do the name resolution separately
    10099                    for each port, so start it now, then only start on
    101100                    the real sockets once we have an IP
    102                  */
    103                 struct nbt_name name;
    104                 struct composite_context *creq;
    105                 make_nbt_name_server(&name, server_address);
    106                 creq = resolve_name_send(resolve_ctx, multi, &name, result->event_ctx);
    107                 if (composite_nomem(creq, result)) goto failed;
    108                 composite_continue(result, creq, continue_resolve_name, result);
    109                 return result;
    110         }
    111 
    112         /* now we've setup the state we can process the first socket */
    113         connect_multi_next_socket(result);
    114 
    115         if (!NT_STATUS_IS_OK(result->status)) {
    116                 goto failed;
    117         }
     101        */
     102        make_nbt_name_server(&name, server_name);
     103
     104        creq = resolve_name_all_send(resolve_ctx, multi, 0, multi->ports[0], &name, result->event_ctx);
     105        if (composite_nomem(creq, result)) goto failed;
     106
     107        composite_continue(result, creq, continue_resolve_name, result);
    118108
    119109        return result;
     110
    120111
    121112 failed:
     
    149140        if (!composite_is_ok(result)) return;
    150141
    151         /* Form up the particular address we are interested in */
    152         state->addr = socket_address_from_strings(state, state->sock->backend_name,
    153                                                   multi->server_address, multi->ports[next]);
     142        state->addr = socket_address_copy(state, multi->server_address);
    154143        if (composite_nomem(state->addr, result)) return;
     144
     145        socket_address_set_port(state->addr, multi->ports[next]);
    155146
    156147        talloc_steal(state, state->sock);
     
    198189        struct connect_multi_state *multi = talloc_get_type(result->private_data,
    199190                                                            struct connect_multi_state);
    200         const char *addr;
    201 
    202         result->status = resolve_name_recv(creq, multi, &addr);
     191        struct socket_address **addr;
     192
     193        result->status = resolve_name_all_recv(creq, multi, &addr, NULL);
    203194        if (!composite_is_ok(result)) return;
    204195
    205         multi->server_address = addr;
     196        /* Let's just go for the first for now */
     197        multi->server_address = addr[0];
    206198
    207199        connect_multi_next_socket(result);
  • trunk/server/source4/lib/socket/interface.c

    r414 r745  
    2323#include "system/network.h"
    2424#include "lib/socket/netif.h"
     25#include "../lib/util/util_net.h"
    2526#include "../lib/util/dlinklist.h"
    2627
     
    9495        DLIST_ADD_END(*interfaces, iface, struct interface *);
    9596
    96         DEBUG(2,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s));
     97        DEBUG(3,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s));
    9798}
    9899
  • trunk/server/source4/lib/socket/netif.c

    r414 r745  
    3535#include "system/network.h"
    3636#include "netif.h"
     37#include "lib/util/tsort.h"
    3738
    3839/****************************************************************************
     
    110111
    111112        /* now we need to remove duplicates */
    112         qsort(ifaces, total, sizeof(ifaces[0]), QSORT_CAST iface_comp);
     113        TYPESAFE_QSORT(ifaces, total, iface_comp);
    113114
    114115        for (i=1;i<total;) {
  • trunk/server/source4/lib/socket/socket.c

    r414 r745  
    2525#include "system/network.h"
    2626#include "param/param.h"
     27#include "../lib/tsocket/tsocket.h"
     28#include "lib/util/util_net.h"
    2729
    2830/*
     
    343345
    344346        return sock->ops->fn_get_my_addr(sock, mem_ctx);
     347}
     348
     349_PUBLIC_ struct tsocket_address *socket_address_to_tsocket_address(TALLOC_CTX *mem_ctx,
     350                                                                   const struct socket_address *a)
     351{
     352        struct tsocket_address *r;
     353        int ret;
     354
     355        if (a->sockaddr) {
     356                ret = tsocket_address_bsd_from_sockaddr(mem_ctx,
     357                                                        a->sockaddr,
     358                                                        a->sockaddrlen,
     359                                                        &r);
     360        } else {
     361                ret = tsocket_address_inet_from_strings(mem_ctx,
     362                                                        a->family,
     363                                                        a->addr,
     364                                                        a->port,
     365                                                        &r);
     366        }
     367
     368        if (ret != 0) {
     369                return NULL;
     370        }
     371
     372        return r;
     373}
     374
     375_PUBLIC_ void socket_address_set_port(struct socket_address *a,
     376                                      uint16_t port)
     377{
     378        if (a->sockaddr) {
     379                set_sockaddr_port(a->sockaddr, port);
     380        } else {
     381                a->port = port;
     382        }
     383
     384}
     385
     386_PUBLIC_ struct socket_address *tsocket_address_to_socket_address(TALLOC_CTX *mem_ctx,
     387                                                                  const struct tsocket_address *a)
     388{
     389        ssize_t ret;
     390        struct sockaddr_storage ss;
     391        size_t sslen = sizeof(ss);
     392
     393        ret = tsocket_address_bsd_sockaddr(a, (struct sockaddr *)(void *)&ss, sslen);
     394        if (ret < 0) {
     395                return NULL;
     396        }
     397
     398        return socket_address_from_sockaddr(mem_ctx, (struct sockaddr *)(void *)&ss, ret);
     399}
     400
     401_PUBLIC_ struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     402{
     403        struct socket_address *a;
     404        struct tsocket_address *r;
     405
     406        a = socket_get_peer_addr(sock, mem_ctx);
     407        if (a == NULL) {
     408                return NULL;
     409        }
     410
     411        r = socket_address_to_tsocket_address(mem_ctx, a);
     412        talloc_free(a);
     413        return r;
     414}
     415
     416_PUBLIC_ struct tsocket_address *socket_get_local_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     417{
     418        struct socket_address *a;
     419        struct tsocket_address *r;
     420
     421        a = socket_get_my_addr(sock, mem_ctx);
     422        if (a == NULL) {
     423                return NULL;
     424        }
     425
     426        r = socket_address_to_tsocket_address(mem_ctx, a);
     427        talloc_free(a);
     428        return r;
    345429}
    346430
  • trunk/server/source4/lib/socket/socket.h

    r414 r745  
    128128
    129129struct resolve_context;
     130struct tsocket_address;
    130131
    131132/* prototypes */
     
    159160struct socket_address *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx);
    160161struct socket_address *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx);
     162struct tsocket_address *socket_address_to_tsocket_address(TALLOC_CTX *mem_ctx,
     163                                                          const struct socket_address *a);
     164struct socket_address *tsocket_address_to_socket_address(TALLOC_CTX *mem_ctx,
     165                                                         const struct tsocket_address *a);
     166struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx);
     167struct tsocket_address *socket_get_local_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx);
    161168int socket_get_fd(struct socket_context *sock);
    162169NTSTATUS socket_dup(struct socket_context *sock);
     
    168175                                                    struct sockaddr *sockaddr,
    169176                                                    size_t addrlen);
     177_PUBLIC_ void socket_address_set_port(struct socket_address *a,
     178                                      uint16_t port);
    170179struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx,
    171180                                           const struct socket_address *oaddr);
     
    207216                              uint16_t *port);
    208217void set_socket_options(int fd, const char *options);
    209 void socket_set_flags(struct socket_context *socket, unsigned flags);
     218void socket_set_flags(struct socket_context *sock, unsigned flags);
    210219
    211220void socket_tevent_fd_close_fn(struct tevent_context *ev,
  • trunk/server/source4/lib/socket/socket_ip.c

    r414 r745  
    2626#include "lib/socket/socket.h"
    2727#include "system/network.h"
     28#include "lib/util/util_net.h"
    2829
    2930static NTSTATUS ipv4_init(struct socket_context *sock)
     
    712713static NTSTATUS ipv6_tcp_accept(struct socket_context *sock, struct socket_context **new_sock)
    713714{
    714         struct sockaddr_in cli_addr;
     715        struct sockaddr_in6 cli_addr;
    715716        socklen_t cli_addr_len = sizeof(cli_addr);
    716717        int new_fd;
  • trunk/server/source4/lib/socket/testsuite.c

    r414 r745  
    4343        struct interface *ifaces;
    4444
    45         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
     45        load_interfaces(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces);
    4646
    4747        status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock1, 0);
     
    136136        talloc_steal(mem_ctx, sock2);
    137137
    138         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
     138        load_interfaces(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces);
    139139        localhost = socket_address_from_strings(sock1, sock1->backend_name,
    140140                                                iface_best_ip(ifaces, "127.0.0.1"), 0);
     
    189189struct torture_suite *torture_local_socket(TALLOC_CTX *mem_ctx)
    190190{
    191         struct torture_suite *suite = torture_suite_create(mem_ctx,
    192                                                                                                            "SOCKET");
     191        struct torture_suite *suite = torture_suite_create(mem_ctx, "socket");
    193192
    194193        torture_suite_add_simple_test(suite, "udp", test_udp);
  • trunk/server/source4/lib/stream/packet.c

    r414 r745  
    4343        int processing;
    4444        bool recv_disable;
     45        bool recv_need_enable;
    4546        bool nofree;
    4647
     
    257258
    258259        if (pc->recv_disable) {
     260                pc->recv_need_enable = true;
    259261                EVENT_FD_NOT_READABLE(pc->fde);
    260262                return;
     
    465467_PUBLIC_ void packet_recv_disable(struct packet_context *pc)
    466468{
    467         EVENT_FD_NOT_READABLE(pc->fde);
    468469        pc->recv_disable = true;
    469470}
     
    474475_PUBLIC_ void packet_recv_enable(struct packet_context *pc)
    475476{
    476         EVENT_FD_READABLE(pc->fde);
     477        if (pc->recv_need_enable) {
     478                pc->recv_need_enable = false;
     479                EVENT_FD_READABLE(pc->fde);
     480        }
    477481        pc->recv_disable = false;
    478482        if (pc->num_read != 0 && pc->packet_size >= pc->num_read) {
     
    527531  call send_callback. 
    528532
    529   Useful for operations that must occour after sending a message, such
     533  Useful for operations that must occur after sending a message, such
    530534  as the switch to SASL encryption after as sucessful LDAP bind relpy.
    531535*/
  • trunk/server/source4/lib/stream/packet.h

    r414 r745  
    2424struct tevent_context;
    2525struct tevent_fd;
     26struct socket_context;
    2627
    2728typedef NTSTATUS (*packet_full_request_fn_t)(void *private_data,
  • trunk/server/source4/lib/tls/tls.c

    r414 r745  
    358358        int ret;
    359359        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    360         const char *keyfile = lp_tls_keyfile(tmp_ctx, lp_ctx);
    361         const char *certfile = lp_tls_certfile(tmp_ctx, lp_ctx);
    362         const char *cafile = lp_tls_cafile(tmp_ctx, lp_ctx);
    363         const char *crlfile = lp_tls_crlfile(tmp_ctx, lp_ctx);
    364         const char *dhpfile = lp_tls_dhpfile(tmp_ctx, lp_ctx);
     360        const char *keyfile = lpcfg_tls_keyfile(tmp_ctx, lp_ctx);
     361        const char *certfile = lpcfg_tls_certfile(tmp_ctx, lp_ctx);
     362        const char *cafile = lpcfg_tls_cafile(tmp_ctx, lp_ctx);
     363        const char *crlfile = lpcfg_tls_crlfile(tmp_ctx, lp_ctx);
     364        const char *dhpfile = lpcfg_tls_dhpfile(tmp_ctx, lp_ctx);
    365365        void tls_cert_generate(TALLOC_CTX *, const char *, const char *, const char *, const char *);
    366366        params = talloc(mem_ctx, struct tls_params);
     
    370370        }
    371371
    372         if (!lp_tls_enabled(lp_ctx) || keyfile == NULL || *keyfile == 0) {
     372        if (!lpcfg_tls_enabled(lp_ctx) || keyfile == NULL || *keyfile == 0) {
    373373                params->tls_enabled = false;
    374374                talloc_free(tmp_ctx);
     
    378378        if (!file_exist(cafile)) {
    379379                char *hostname = talloc_asprintf(mem_ctx, "%s.%s",
    380                                                  lp_netbios_name(lp_ctx), lp_realm(lp_ctx));
     380                                                 lpcfg_netbios_name(lp_ctx),
     381                                                 lpcfg_dnsdomain(lp_ctx));
    381382                if (hostname == NULL) {
    382383                        goto init_failed;
  • trunk/server/source4/lib/tls/tls.h

    r414 r745  
    6666const struct socket_ops *socket_tls_ops(enum socket_type type);
    6767
    68 #endif
     68struct tstream_context;
     69struct tstream_tls_params;
     70
     71NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
     72                                   const char *ca_file,
     73                                   const char *crl_file,
     74                                   struct tstream_tls_params **_tlsp);
     75
     76NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
     77                                   const char *dns_host_name,
     78                                   bool enabled,
     79                                   const char *key_file,
     80                                   const char *cert_file,
     81                                   const char *ca_file,
     82                                   const char *crl_file,
     83                                   const char *dhp_file,
     84                                   struct tstream_tls_params **_params);
     85
     86bool tstream_tls_params_enabled(struct tstream_tls_params *params);
     87
     88struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
     89                                             struct tevent_context *ev,
     90                                             struct tstream_context *plain_stream,
     91                                             struct tstream_tls_params *tls_params,
     92                                             const char *location);
     93#define tstream_tls_connect_send(mem_ctx, ev, plain_stream, tls_params); \
     94        _tstream_tls_connect_send(mem_ctx, ev, plain_stream, tls_params, __location__)
     95
     96int tstream_tls_connect_recv(struct tevent_req *req,
     97                             int *perrno,
     98                             TALLOC_CTX *mem_ctx,
     99                             struct tstream_context **tls_stream);
     100
     101struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
     102                                            struct tevent_context *ev,
     103                                            struct tstream_context *plain_stream,
     104                                            struct tstream_tls_params *tls_params,
     105                                            const char *location);
     106#define tstream_tls_accept_send(mem_ctx, ev, plain_stream, tls_params) \
     107        _tstream_tls_accept_send(mem_ctx, ev, plain_stream, tls_params, __location__)
     108
     109int tstream_tls_accept_recv(struct tevent_req *req,
     110                            int *perrno,
     111                            TALLOC_CTX *mem_ctx,
     112                            struct tstream_context **tls_stream);
     113
     114#endif /* _TLS_H_ */
  • trunk/server/source4/lib/tls/tlscert.c

    r414 r745  
    139139        bufsize = sizeof(buf);
    140140        TLSCHECK(gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buf, &bufsize));
    141         file_save(certfile, buf, bufsize);
     141        if (!file_save(certfile, buf, bufsize)) {
     142                DEBUG(0,("Unable to save certificate in %s parent dir exists ?\n", certfile));
     143                goto failed;
     144        }
    142145
    143146        bufsize = sizeof(buf);
    144147        TLSCHECK(gnutls_x509_crt_export(cacrt, GNUTLS_X509_FMT_PEM, buf, &bufsize));
    145         file_save(cafile, buf, bufsize);
     148        if (!file_save(cafile, buf, bufsize)) {
     149                DEBUG(0,("Unable to save ca cert in %s parent dir exists ?\n", cafile));
     150                goto failed;
     151        }
    146152
    147153        bufsize = sizeof(buf);
    148154        TLSCHECK(gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buf, &bufsize));
    149         file_save(keyfile, buf, bufsize);
     155        if (!file_save(keyfile, buf, bufsize)) {
     156                DEBUG(0,("Unable to save privatekey in %s parent dir exists ?\n", keyfile));
     157                goto failed;
     158        }
    150159
    151160        gnutls_x509_privkey_deinit(key);
  • trunk/server/source4/lib/wmi/tools/wmic.c

    r414 r745  
    3636
    3737struct program_args {
    38         char *hostname;
    39         char *query;
    40         char *ns;
     38    char *hostname;
     39    char *query;
     40    char *ns;
    4141};
    4242
    4343static void parse_args(int argc, char *argv[], struct program_args *pmyargs)
    4444{
    45         poptContext pc;
    46         int opt, i;
    47 
    48         int argc_new;
    49         char **argv_new;
    50 
    51         struct poptOption long_options[] = {
    52                 POPT_AUTOHELP
    53                 POPT_COMMON_SAMBA
    54                 POPT_COMMON_CONNECTION
    55                 POPT_COMMON_CREDENTIALS
    56                 POPT_COMMON_VERSION
    57                 {"namespace", 0, POPT_ARG_STRING, &pmyargs->ns, 0,
    58                  "WMI namespace, default to root\\cimv2", 0},
    59                 POPT_TABLEEND
    60         };
    61 
    62         pc = poptGetContext("wmi", argc, (const char **) argv,
    63                 long_options, POPT_CONTEXT_KEEP_FIRST);
    64 
    65         poptSetOtherOptionHelp(pc, "//host query\n\nExample: wmic -U [domain/]adminuser%password //host \"select * from Win32_ComputerSystem\"");
    66 
    67         while ((opt = poptGetNextOpt(pc)) != -1) {
    68                 poptPrintUsage(pc, stdout, 0);
    69                 poptFreeContext(pc);
    70                 exit(1);
     45    poptContext pc;
     46    int opt, i;
     47
     48    int argc_new;
     49    char **argv_new;
     50
     51    struct poptOption long_options[] = {
     52        POPT_AUTOHELP
     53        POPT_COMMON_SAMBA
     54        POPT_COMMON_CONNECTION
     55        POPT_COMMON_CREDENTIALS
     56        POPT_COMMON_VERSION
     57        {"namespace", 0, POPT_ARG_STRING, &pmyargs->ns, 0,
     58         "WMI namespace, default to root\\cimv2", 0},
     59        POPT_TABLEEND
     60    };
     61
     62    pc = poptGetContext("wmi", argc, (const char **) argv,
     63                long_options, POPT_CONTEXT_KEEP_FIRST);
     64
     65    poptSetOtherOptionHelp(pc, "//host query\n\nExample: wmic -U [domain/]adminuser%password //host \"select * from Win32_ComputerSystem\"");
     66
     67    while ((opt = poptGetNextOpt(pc)) != -1) {
     68        poptPrintUsage(pc, stdout, 0);
     69        poptFreeContext(pc);
     70        exit(1);
     71    }
     72
     73    argv_new = discard_const_p(char *, poptGetArgs(pc));
     74
     75    argc_new = argc;
     76    for (i = 0; i < argc; i++) {
     77        if (argv_new[i] == NULL) {
     78            argc_new = i;
     79            break;
    7180        }
    72 
    73         argv_new = discard_const_p(char *, poptGetArgs(pc));
    74 
    75         argc_new = argc;
    76         for (i = 0; i < argc; i++) {
    77                 if (argv_new[i] == NULL) {
    78                         argc_new = i;
    79                         break;
    80                 }
    81         }
    82 
    83         if (argc_new != 3 || argv_new[1][0] != '/'
    84                         || argv_new[1][1] != '/') {
    85                 poptPrintUsage(pc, stdout, 0);
    86                 poptFreeContext(pc);
    87                 exit(1);
    88         }
    89 
    90         pmyargs->hostname = argv_new[1] + 2;
    91         pmyargs->query = argv_new[2];
     81    }
     82
     83    if (argc_new != 3 || argv_new[1][0] != '/'
     84        || argv_new[1][1] != '/') {
     85        poptPrintUsage(pc, stdout, 0);
    9286        poptFreeContext(pc);
    93 }
    94 
    95 static void escape_string(const char *src, char *dst, int len)
    96 {
    97         char *p = dst, *end = dst + len - 1;
    98         const char *q = src;
    99 
    100         if ( q == NULL) {
    101                 strncpy( dst, "(null)", len);
    102                 return;
    103         }
    104 
    105         while ( *q && p <= end ) {
    106                 if ( strchr( "|\\(),", *q)) {
    107                         *p++ = '\\';
    108                         *p++ = *q++;
    109                 } else if ( *q == '\n' ) {
    110                         *p++ = '\\';
    111                         *p++ = 'n';
    112                         q++;
    113                 } else if ( *q == '\r' ) {
    114                         *p++ = '\\';
    115                         *p++ = 'r';
    116                         q++;
    117                 } else {
    118                         *p++ = *q++;
    119                 }
    120         }
    121 
    122         *p++ = 0;
     87        exit(1);
     88    }
     89
     90    pmyargs->hostname = argv_new[1] + 2;
     91    pmyargs->query = argv_new[2];
     92    poptFreeContext(pc);
    12393}
    12494
     
    130100                        }
    131101
    132 #define RETURN_CVAR_ARRAY_STR_START(arr) {\
    133         uint32_t i;\
     102#define RETURN_CVAR_ARRAY_STR(fmt, arr) {\
     103        uint32_t i;\
    134104        char *r;\
    135105\
    136         if (!arr) {\
    137                 return talloc_strdup(mem_ctx, "(null)");\
    138         }\
     106        if (!arr) {\
     107                return talloc_strdup(mem_ctx, "NULL");\
     108        }\
    139109        r = talloc_strdup(mem_ctx, "(");\
    140         for (i = 0; i < arr->count; ++i) {
    141 
    142 
    143 #define RETURN_CVAR_ARRAY_STR_END(fmt, arr, item) \
    144                 r = talloc_asprintf_append(r, fmt "%s", item, (i+1 == arr->count)?"":",");\
    145         }\
    146         return talloc_asprintf_append(r, ")");\
    147 }
    148 
    149 #define RETURN_CVAR_ARRAY_STR(fmt, arr) \
    150         RETURN_CVAR_ARRAY_STR_START(arr) \
    151         RETURN_CVAR_ARRAY_STR_END(fmt, arr, arr->item[i])
    152 
    153 #define RETURN_CVAR_ARRAY_ESCAPED(fmt, arr) \
    154         RETURN_CVAR_ARRAY_STR_START(arr) \
    155         char buf[2048]; \
    156         escape_string( arr->item[i], buf, 2048); \
    157         RETURN_CVAR_ARRAY_STR_END(fmt, arr, buf)
     110        for (i = 0; i < arr->count; ++i) {\
     111                r = talloc_asprintf_append(r, fmt "%s", arr->item[i], (i+1 == arr->count)?"":",");\
     112        }\
     113        return talloc_asprintf_append(r, ")");\
     114}
    158115
    159116char *string_CIMVAR(TALLOC_CTX *mem_ctx, union CIMVAR *v, enum CIMTYPE_ENUMERATION cimtype)
     
    173130        case CIM_STRING:
    174131        case CIM_DATETIME:
    175         case CIM_REFERENCE: {
    176                 char buf[2048];
    177                 escape_string((char*) v-> v_string, buf, 2048);
    178                 return talloc_asprintf(mem_ctx, "%s", buf);
    179         }
     132        case CIM_REFERENCE: return talloc_asprintf(mem_ctx, "%s", v->v_string);
    180133        case CIM_CHAR16: return talloc_asprintf(mem_ctx, "Unsupported");
    181134        case CIM_OBJECT: return talloc_asprintf(mem_ctx, "Unsupported");
     
    191144        case CIM_ARR_REAL64: RETURN_CVAR_ARRAY_STR("%f", v->a_real64);
    192145        case CIM_ARR_BOOLEAN: RETURN_CVAR_ARRAY_STR("%d", v->a_boolean);
    193         case CIM_ARR_STRING: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_string);
    194         case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_datetime);
    195         case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_reference);
     146        case CIM_ARR_STRING: RETURN_CVAR_ARRAY_STR("%s", v->a_string);
     147        case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY_STR("%s", v->a_datetime);
     148        case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY_STR("%s", v->a_reference);
    196149        default: return talloc_asprintf(mem_ctx, "Unsupported");
    197150        }
Note: See TracChangeset for help on using the changeset viewer.