Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (12 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified vendor/current/source4/dsdb/schema/schema_syntax.c

    r414 r740  
    1 /* 
     1/*
    22   Unix SMB/CIFS mplementation.
    33   DSDB schema syntaxes
    4    
     4
    55   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
    66   Copyright (C) Simo Sorce 2005
     
    1111   the Free Software Foundation; either version 3 of the License, or
    1212   (at your option) any later version.
    13    
     13
    1414   This program is distributed in the hope that it will be useful,
    1515   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1616   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1717   GNU General Public License for more details.
    18    
     18
    1919   You should have received a copy of the GNU General Public License
    2020   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    21    
     21
    2222*/
    2323#include "includes.h"
     
    2626#include "librpc/gen_ndr/ndr_security.h"
    2727#include "librpc/gen_ndr/ndr_misc.h"
    28 #include "lib/ldb/include/ldb.h"
    29 #include "lib/ldb/include/ldb_errors.h"
     28#include <ldb.h>
     29#include <ldb_errors.h>
    3030#include "system/time.h"
    3131#include "../lib/util/charset/charset.h"
    3232#include "librpc/ndr/libndr.h"
    33 
    34 static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(struct ldb_context *ldb,
    35                                                 const struct dsdb_schema *schema,
     33#include "../lib/util/asn1.h"
     34
     35/**
     36 * Initialize dsdb_syntax_ctx with default values
     37 * for common cases.
     38 */
     39void dsdb_syntax_ctx_init(struct dsdb_syntax_ctx *ctx,
     40                          struct ldb_context *ldb,
     41                          const struct dsdb_schema *schema)
     42{
     43        ctx->ldb        = ldb;
     44        ctx->schema     = schema;
     45
     46        /*
     47         * 'true' will keep current behavior,
     48         * i.e. attributeID_id will be returned by default
     49         */
     50        ctx->is_schema_nc = true;
     51
     52        ctx->pfm_remote = NULL;
     53}
     54
     55
     56/**
     57 * Returns ATTID for DRS attribute.
     58 *
     59 * ATTID depends on whether we are replicating
     60 * Schema NC or msDs-IntId is set for schemaAttribute
     61 * for the attribute.
     62 */
     63uint32_t dsdb_attribute_get_attid(const struct dsdb_attribute *attr,
     64                                  bool for_schema_nc)
     65{
     66        if (!for_schema_nc && attr->msDS_IntId) {
     67                return attr->msDS_IntId;
     68        }
     69
     70        return attr->attributeID_id;
     71}
     72
     73/**
     74 * Map an ATTID from remote DC to a local ATTID
     75 * using remote prefixMap
     76 */
     77static bool dsdb_syntax_attid_from_remote_attid(const struct dsdb_syntax_ctx *ctx,
     78                                                TALLOC_CTX *mem_ctx,
     79                                                uint32_t id_remote,
     80                                                uint32_t *id_local)
     81{
     82        WERROR werr;
     83        const char *oid;
     84
     85        /*
     86         * map remote ATTID to local directly in case
     87         * of no remote prefixMap (during provision for instance)
     88         */
     89        if (!ctx->pfm_remote) {
     90                *id_local = id_remote;
     91                return true;
     92        }
     93
     94        werr = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, id_remote, mem_ctx, &oid);
     95        if (!W_ERROR_IS_OK(werr)) {
     96                DEBUG(0,("ATTID->OID failed (%s) for: 0x%08X\n", win_errstr(werr), id_remote));
     97                return false;
     98        }
     99
     100        werr = dsdb_schema_pfm_make_attid(ctx->schema->prefixmap, oid, id_local);
     101        if (!W_ERROR_IS_OK(werr)) {
     102                DEBUG(0,("OID->ATTID failed (%s) for: %s\n", win_errstr(werr), oid));
     103                return false;
     104        }
     105
     106        return true;
     107}
     108
     109static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    36110                                                const struct dsdb_attribute *attr,
    37111                                                const struct drsuapi_DsReplicaAttribute *in,
     
    39113                                                struct ldb_message_element *out)
    40114{
    41         uint32_t i;
     115        unsigned int i;
    42116
    43117        out->flags      = 0;
     
    66140}
    67141
    68 static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(struct ldb_context *ldb,
    69                                                 const struct dsdb_schema *schema,
     142static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    70143                                                const struct dsdb_attribute *attr,
    71144                                                const struct ldb_message_element *in,
     
    76149}
    77150
    78 static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(struct ldb_context *ldb,
    79                                               const struct dsdb_schema *schema,
     151static WERROR dsdb_syntax_FOOBAR_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     152                                              const struct dsdb_attribute *attr,
     153                                              const struct ldb_message_element *in)
     154{
     155        return WERR_FOOBAR;
     156}
     157
     158static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    80159                                              const struct dsdb_attribute *attr,
    81160                                              const struct drsuapi_DsReplicaAttribute *in,
     
    83162                                              struct ldb_message_element *out)
    84163{
    85         uint32_t i;
     164        unsigned int i;
    86165
    87166        out->flags      = 0;
     
    121200}
    122201
    123 static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(struct ldb_context *ldb,
    124                                               const struct dsdb_schema *schema,
     202static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    125203                                              const struct dsdb_attribute *attr,
    126204                                              const struct ldb_message_element *in,
     
    128206                                              struct drsuapi_DsReplicaAttribute *out)
    129207{
    130         uint32_t i;
     208        unsigned int i;
    131209        DATA_BLOB *blobs;
    132210
    133         if (attr->attributeID_id == 0xFFFFFFFF) {
    134                 return WERR_FOOBAR;
    135         }
    136 
    137         out->attid                      = attr->attributeID_id;
     211        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     212                return WERR_FOOBAR;
     213        }
     214
     215        out->attid                      = dsdb_attribute_get_attid(attr,
     216                                                                   ctx->is_schema_nc);
    138217        out->value_ctr.num_values       = in->num_values;
    139218        out->value_ctr.values           = talloc_array(mem_ctx,
     
    163242}
    164243
    165 static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(struct ldb_context *ldb,
    166                                                const struct dsdb_schema *schema,
     244static WERROR dsdb_syntax_BOOL_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     245                                            const struct dsdb_attribute *attr,
     246                                            const struct ldb_message_element *in)
     247{
     248        unsigned int i;
     249
     250        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     251                return WERR_FOOBAR;
     252        }
     253
     254        for (i=0; i < in->num_values; i++) {
     255                int t, f;
     256
     257                t = strncmp("TRUE",
     258                            (const char *)in->values[i].data,
     259                            in->values[i].length);
     260                f = strncmp("FALSE",
     261                            (const char *)in->values[i].data,
     262                            in->values[i].length);
     263
     264                if (t != 0 && f != 0) {
     265                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     266                }
     267        }
     268
     269        return WERR_OK;
     270}
     271
     272static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    167273                                               const struct dsdb_attribute *attr,
    168274                                               const struct drsuapi_DsReplicaAttribute *in,
     
    170276                                               struct ldb_message_element *out)
    171277{
    172         uint32_t i;
     278        unsigned int i;
    173279
    174280        out->flags      = 0;
     
    203309}
    204310
    205 static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(struct ldb_context *ldb,
    206                                                const struct dsdb_schema *schema,
     311static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    207312                                               const struct dsdb_attribute *attr,
    208313                                               const struct ldb_message_element *in,
     
    210315                                               struct drsuapi_DsReplicaAttribute *out)
    211316{
    212         uint32_t i;
     317        unsigned int i;
    213318        DATA_BLOB *blobs;
    214319
    215         if (attr->attributeID_id == 0xFFFFFFFF) {
    216                 return WERR_FOOBAR;
    217         }
    218 
    219         out->attid                      = attr->attributeID_id;
     320        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     321                return WERR_FOOBAR;
     322        }
     323
     324        out->attid                      = dsdb_attribute_get_attid(attr,
     325                                                                   ctx->is_schema_nc);
    220326        out->value_ctr.num_values       = in->num_values;
    221327        out->value_ctr.values           = talloc_array(mem_ctx,
     
    245351}
    246352
    247 static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(struct ldb_context *ldb,
    248                                                const struct dsdb_schema *schema,
     353static WERROR dsdb_syntax_INT32_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     354                                             const struct dsdb_attribute *attr,
     355                                             const struct ldb_message_element *in)
     356{
     357        unsigned int i;
     358
     359        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     360                return WERR_FOOBAR;
     361        }
     362
     363        for (i=0; i < in->num_values; i++) {
     364                long v;
     365                char buf[sizeof("-2147483648")];
     366                char *end = NULL;
     367
     368                ZERO_STRUCT(buf);
     369                if (in->values[i].length >= sizeof(buf)) {
     370                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     371                }
     372
     373                memcpy(buf, in->values[i].data, in->values[i].length);
     374                errno = 0;
     375                v = strtol(buf, &end, 10);
     376                if (errno != 0) {
     377                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     378                }
     379                if (end && end[0] != '\0') {
     380                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     381                }
     382
     383                if (attr->rangeLower) {
     384                        if ((int32_t)v < (int32_t)*attr->rangeLower) {
     385                                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     386                        }
     387                }
     388
     389                if (attr->rangeUpper) {
     390                        if ((int32_t)v > (int32_t)*attr->rangeUpper) {
     391                                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     392                        }
     393                }
     394        }
     395
     396        return WERR_OK;
     397}
     398
     399static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    249400                                               const struct dsdb_attribute *attr,
    250401                                               const struct drsuapi_DsReplicaAttribute *in,
     
    252403                                               struct ldb_message_element *out)
    253404{
    254         uint32_t i;
     405        unsigned int i;
    255406
    256407        out->flags      = 0;
     
    285436}
    286437
    287 static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(struct ldb_context *ldb,
    288                                                const struct dsdb_schema *schema,
     438static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    289439                                               const struct dsdb_attribute *attr,
    290440                                               const struct ldb_message_element *in,
     
    292442                                               struct drsuapi_DsReplicaAttribute *out)
    293443{
    294         uint32_t i;
     444        unsigned int i;
    295445        DATA_BLOB *blobs;
    296446
    297         if (attr->attributeID_id == 0xFFFFFFFF) {
    298                 return WERR_FOOBAR;
    299         }
    300 
    301         out->attid                      = attr->attributeID_id;
     447        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     448                return WERR_FOOBAR;
     449        }
     450
     451        out->attid                      = dsdb_attribute_get_attid(attr,
     452                                                                   ctx->is_schema_nc);
    302453        out->value_ctr.num_values       = in->num_values;
    303454        out->value_ctr.values           = talloc_array(mem_ctx,
     
    325476}
    326477
    327 static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(struct ldb_context *ldb,
    328                                                     const struct dsdb_schema *schema,
     478static WERROR dsdb_syntax_INT64_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     479                                             const struct dsdb_attribute *attr,
     480                                             const struct ldb_message_element *in)
     481{
     482        unsigned int i;
     483
     484        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     485                return WERR_FOOBAR;
     486        }
     487
     488        for (i=0; i < in->num_values; i++) {
     489                long long v;
     490                char buf[sizeof("-9223372036854775808")];
     491                char *end = NULL;
     492
     493                ZERO_STRUCT(buf);
     494                if (in->values[i].length >= sizeof(buf)) {
     495                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     496                }
     497                memcpy(buf, in->values[i].data, in->values[i].length);
     498
     499                errno = 0;
     500                v = strtoll(buf, &end, 10);
     501                if (errno != 0) {
     502                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     503                }
     504                if (end && end[0] != '\0') {
     505                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     506                }
     507
     508                if (attr->rangeLower) {
     509                        if ((int64_t)v < (int64_t)*attr->rangeLower) {
     510                                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     511                        }
     512                }
     513
     514                if (attr->rangeUpper) {
     515                        if ((int64_t)v > (int64_t)*attr->rangeUpper) {
     516                                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     517                        }
     518                }
     519        }
     520
     521        return WERR_OK;
     522}
     523static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    329524                                                    const struct dsdb_attribute *attr,
    330525                                                    const struct drsuapi_DsReplicaAttribute *in,
     
    332527                                                    struct ldb_message_element *out)
    333528{
    334         uint32_t i;
     529        unsigned int i;
    335530
    336531        out->flags      = 0;
     
    359554                t = nt_time_to_unix(v);
    360555
    361                 /* 
     556                /*
    362557                 * NOTE: On a w2k3 server you can set a GeneralizedTime string
    363558                 *       via LDAP, but you get back an UTCTime string,
     
    368563                 *       we'll loose information!
    369564                 */
    370                 str = ldb_timestring_utc(out->values, t); 
     565                str = ldb_timestring_utc(out->values, t);
    371566                W_ERROR_HAVE_NO_MEMORY(str);
    372567                out->values[i] = data_blob_string_const(str);
     
    376571}
    377572
    378 static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(struct ldb_context *ldb,
    379                                                     const struct dsdb_schema *schema,
     573static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    380574                                                    const struct dsdb_attribute *attr,
    381575                                                    const struct ldb_message_element *in,
     
    383577                                                    struct drsuapi_DsReplicaAttribute *out)
    384578{
    385         uint32_t i;
     579        unsigned int i;
    386580        DATA_BLOB *blobs;
    387581
    388         if (attr->attributeID_id == 0xFFFFFFFF) {
    389                 return WERR_FOOBAR;
    390         }
    391 
    392         out->attid                      = attr->attributeID_id;
     582        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     583                return WERR_FOOBAR;
     584        }
     585
     586        out->attid                      = dsdb_attribute_get_attid(attr,
     587                                                                   ctx->is_schema_nc);
    393588        out->value_ctr.num_values       = in->num_values;
    394589        out->value_ctr.values           = talloc_array(mem_ctx,
     
    419614}
    420615
    421 static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(struct ldb_context *ldb,
    422                                                 const struct dsdb_schema *schema,
     616static WERROR dsdb_syntax_NTTIME_UTC_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     617                                                  const struct dsdb_attribute *attr,
     618                                                  const struct ldb_message_element *in)
     619{
     620        unsigned int i;
     621
     622        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     623                return WERR_FOOBAR;
     624        }
     625
     626        for (i=0; i < in->num_values; i++) {
     627                time_t t;
     628                char buf[sizeof("090826075717Z")];
     629
     630                ZERO_STRUCT(buf);
     631                if (in->values[i].length >= sizeof(buf)) {
     632                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     633                }
     634                memcpy(buf, in->values[i].data, in->values[i].length);
     635
     636                errno = 0;
     637                t = ldb_string_utc_to_time(buf);
     638                if (errno != 0) {
     639                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     640                }
     641
     642                if (attr->rangeLower) {
     643                        if ((int32_t)t < (int32_t)*attr->rangeLower) {
     644                                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     645                        }
     646                }
     647
     648                if (attr->rangeUpper) {
     649                        if ((int32_t)t > (int32_t)*attr->rangeLower) {
     650                                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     651                        }
     652                }
     653
     654                /*
     655                 * TODO: verify the comment in the
     656                 * dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb() function!
     657                 */
     658        }
     659
     660        return WERR_OK;
     661}
     662
     663static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    423664                                                const struct dsdb_attribute *attr,
    424665                                                const struct drsuapi_DsReplicaAttribute *in,
     
    426667                                                struct ldb_message_element *out)
    427668{
    428         uint32_t i;
     669        unsigned int i;
    429670
    430671        out->flags      = 0;
     
    453694                t = nt_time_to_unix(v);
    454695
    455                 str = ldb_timestring(out->values, t); 
     696                str = ldb_timestring(out->values, t);
    456697                W_ERROR_HAVE_NO_MEMORY(str);
    457698
     
    462703}
    463704
    464 static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(struct ldb_context *ldb,
    465                                                 const struct dsdb_schema *schema,
     705static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    466706                                                const struct dsdb_attribute *attr,
    467707                                                const struct ldb_message_element *in,
     
    469709                                                struct drsuapi_DsReplicaAttribute *out)
    470710{
    471         uint32_t i;
     711        unsigned int i;
    472712        DATA_BLOB *blobs;
    473713
    474         if (attr->attributeID_id == 0xFFFFFFFF) {
    475                 return WERR_FOOBAR;
    476         }
    477 
    478         out->attid                      = attr->attributeID_id;
     714        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     715                return WERR_FOOBAR;
     716        }
     717
     718        out->attid                      = dsdb_attribute_get_attid(attr,
     719                                                                   ctx->is_schema_nc);
    479720        out->value_ctr.num_values       = in->num_values;
    480721        out->value_ctr.values           = talloc_array(mem_ctx,
     
    489730                NTTIME v;
    490731                time_t t;
     732                int ret;
    491733
    492734                out->value_ctr.values[i].blob   = &blobs[i];
     
    495737                W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
    496738
    497                 t = ldb_string_to_time((const char *)in->values[i].data);
     739                ret = ldb_val_to_time(&in->values[i], &t);
     740                if (ret != LDB_SUCCESS) {
     741                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     742                }
    498743                unix_to_nt_time(&v, t);
    499744                v /= 10000000;
     
    505750}
    506751
    507 static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(struct ldb_context *ldb,
    508                                                    const struct dsdb_schema *schema,
     752static WERROR dsdb_syntax_NTTIME_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     753                                              const struct dsdb_attribute *attr,
     754                                              const struct ldb_message_element *in)
     755{
     756        unsigned int i;
     757
     758        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     759                return WERR_FOOBAR;
     760        }
     761
     762        for (i=0; i < in->num_values; i++) {
     763                time_t t;
     764                int ret;
     765
     766                ret = ldb_val_to_time(&in->values[i], &t);
     767                if (ret != LDB_SUCCESS) {
     768                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     769                }
     770
     771                if (attr->rangeLower) {
     772                        if ((int32_t)t < (int32_t)*attr->rangeLower) {
     773                                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     774                        }
     775                }
     776
     777                if (attr->rangeUpper) {
     778                        if ((int32_t)t > (int32_t)*attr->rangeLower) {
     779                                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     780                        }
     781                }
     782        }
     783
     784        return WERR_OK;
     785}
     786
     787static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    509788                                                   const struct dsdb_attribute *attr,
    510789                                                   const struct drsuapi_DsReplicaAttribute *in,
     
    512791                                                   struct ldb_message_element *out)
    513792{
    514         uint32_t i;
     793        unsigned int i;
    515794
    516795        out->flags      = 0;
     
    539818}
    540819
    541 static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb,
    542                                                    const struct dsdb_schema *schema,
     820static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    543821                                                   const struct dsdb_attribute *attr,
    544822                                                   const struct ldb_message_element *in,
     
    546824                                                   struct drsuapi_DsReplicaAttribute *out)
    547825{
    548         uint32_t i;
     826        unsigned int i;
    549827        DATA_BLOB *blobs;
    550828
    551         if (attr->attributeID_id == 0xFFFFFFFF) {
    552                 return WERR_FOOBAR;
    553         }
    554 
    555         out->attid                      = attr->attributeID_id;
     829        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     830                return WERR_FOOBAR;
     831        }
     832
     833        out->attid                      = dsdb_attribute_get_attid(attr,
     834                                                                   ctx->is_schema_nc);
    556835        out->value_ctr.num_values       = in->num_values;
    557836        out->value_ctr.values           = talloc_array(mem_ctx,
     
    573852}
    574853
    575 static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb,
    576                                                   const struct dsdb_schema *schema,
     854static WERROR dsdb_syntax_DATA_BLOB_validate_one_val(const struct dsdb_syntax_ctx *ctx,
     855                                                     const struct dsdb_attribute *attr,
     856                                                     const struct ldb_val *val)
     857{
     858        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     859                return WERR_FOOBAR;
     860        }
     861
     862        if (attr->rangeLower) {
     863                if ((uint32_t)val->length < (uint32_t)*attr->rangeLower) {
     864                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     865                }
     866        }
     867
     868        if (attr->rangeUpper) {
     869                if ((uint32_t)val->length > (uint32_t)*attr->rangeUpper) {
     870                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     871                }
     872        }
     873
     874        return WERR_OK;
     875}
     876
     877static WERROR dsdb_syntax_DATA_BLOB_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     878                                                 const struct dsdb_attribute *attr,
     879                                                 const struct ldb_message_element *in)
     880{
     881        unsigned int i;
     882        WERROR status;
     883
     884        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     885                return WERR_FOOBAR;
     886        }
     887
     888        for (i=0; i < in->num_values; i++) {
     889                if (in->values[i].length == 0) {
     890                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     891                }
     892
     893                status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
     894                                                                attr,
     895                                                                &in->values[i]);
     896                if (!W_ERROR_IS_OK(status)) {
     897                        return status;
     898                }
     899        }
     900
     901        return WERR_OK;
     902}
     903
     904static WERROR _dsdb_syntax_auto_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
     905                                                   const struct dsdb_attribute *attr,
     906                                                   const struct drsuapi_DsReplicaAttribute *in,
     907                                                   TALLOC_CTX *mem_ctx,
     908                                                   struct ldb_message_element *out)
     909{
     910        unsigned int i;
     911
     912        out->flags      = 0;
     913        out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
     914        W_ERROR_HAVE_NO_MEMORY(out->name);
     915
     916        out->num_values = in->value_ctr.num_values;
     917        out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
     918        W_ERROR_HAVE_NO_MEMORY(out->values);
     919
     920        for (i=0; i < out->num_values; i++) {
     921                uint32_t v;
     922                const struct dsdb_class *c;
     923                const struct dsdb_attribute *a;
     924                const char *str = NULL;
     925
     926                if (in->value_ctr.values[i].blob == NULL) {
     927                        return WERR_FOOBAR;
     928                }
     929
     930                if (in->value_ctr.values[i].blob->length != 4) {
     931                        return WERR_FOOBAR;
     932                }
     933
     934                v = IVAL(in->value_ctr.values[i].blob->data, 0);
     935
     936                if ((c = dsdb_class_by_governsID_id(ctx->schema, v))) {
     937                        str = talloc_strdup(out->values, c->lDAPDisplayName);
     938                } else if ((a = dsdb_attribute_by_attributeID_id(ctx->schema, v))) {
     939                        str = talloc_strdup(out->values, a->lDAPDisplayName);
     940                } else {
     941                        WERROR werr;
     942                        SMB_ASSERT(ctx->pfm_remote);
     943                        werr = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, v,
     944                                                              out->values, &str);
     945                        W_ERROR_NOT_OK_RETURN(werr);
     946                }
     947                W_ERROR_HAVE_NO_MEMORY(str);
     948
     949                /* the values need to be reversed */
     950                out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
     951        }
     952
     953        return WERR_OK;
     954}
     955
     956static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    577957                                                  const struct dsdb_attribute *attr,
    578958                                                  const struct drsuapi_DsReplicaAttribute *in,
     
    580960                                                  struct ldb_message_element *out)
    581961{
    582         uint32_t i;
     962        unsigned int i;
    583963
    584964        out->flags      = 0;
     
    605985                v = IVAL(in->value_ctr.values[i].blob->data, 0);
    606986
    607                 c = dsdb_class_by_governsID_id(schema, v);
     987                /* convert remote ATTID to local ATTID */
     988                if (!dsdb_syntax_attid_from_remote_attid(ctx, mem_ctx, v, &v)) {
     989                        DEBUG(1,(__location__ ": Failed to map remote ATTID to local ATTID!\n"));
     990                        return WERR_FOOBAR;
     991                }
     992
     993                c = dsdb_class_by_governsID_id(ctx->schema, v);
    608994                if (!c) {
     995                        DEBUG(1,(__location__ ": Unknown governsID 0x%08X\n", v));
    609996                        return WERR_FOOBAR;
    610997                }
     
    6201007}
    6211008
    622 static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(struct ldb_context *ldb,
    623                                                    const struct dsdb_schema *schema,
     1009static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    6241010                                                   const struct dsdb_attribute *attr,
    6251011                                                   const struct drsuapi_DsReplicaAttribute *in,
     
    6271013                                                   struct ldb_message_element *out)
    6281014{
    629         uint32_t i;
     1015        unsigned int i;
    6301016
    6311017        out->flags      = 0;
     
    6521038                v = IVAL(in->value_ctr.values[i].blob->data, 0);
    6531039
    654                 a = dsdb_attribute_by_attributeID_id(schema, v);
     1040                /* convert remote ATTID to local ATTID */
     1041                if (!dsdb_syntax_attid_from_remote_attid(ctx, mem_ctx, v, &v)) {
     1042                        DEBUG(1,(__location__ ": Failed to map remote ATTID to local ATTID!\n"));
     1043                        return WERR_FOOBAR;
     1044                }
     1045
     1046                a = dsdb_attribute_by_attributeID_id(ctx->schema, v);
    6551047                if (!a) {
     1048                        DEBUG(1,(__location__ ": Unknown attributeID_id 0x%08X\n", v));
    6561049                        return WERR_FOOBAR;
    6571050                }
     
    6671060}
    6681061
    669 static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb,
    670                                                   const struct dsdb_schema *schema,
     1062static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    6711063                                                  const struct dsdb_attribute *attr,
    6721064                                                  const struct drsuapi_DsReplicaAttribute *in,
     
    6741066                                                  struct ldb_message_element *out)
    6751067{
    676         uint32_t i;
     1068        unsigned int i;
     1069
     1070        SMB_ASSERT(ctx->pfm_remote);
    6771071
    6781072        out->flags      = 0;
     
    6851079
    6861080        for (i=0; i < out->num_values; i++) {
    687                 uint32_t v;
     1081                uint32_t attid;
    6881082                WERROR status;
    689                 const char *str;
     1083                const char *oid;
    6901084
    6911085                if (in->value_ctr.values[i].blob == NULL) {
     
    6971091                }
    6981092
    699                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
    700 
    701                 status = dsdb_map_int2oid(schema, v, out->values, &str);
    702                 W_ERROR_NOT_OK_RETURN(status);
    703 
    704                 out->values[i] = data_blob_string_const(str);
    705         }
    706 
    707         return WERR_OK;
    708 }
    709 
    710 static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
    711                                                   const struct dsdb_schema *schema,
    712                                                   const struct dsdb_attribute *attr,
    713                                                   const struct ldb_message_element *in,
    714                                                   TALLOC_CTX *mem_ctx,
    715                                                   struct drsuapi_DsReplicaAttribute *out)
    716 {
    717         uint32_t i;
     1093                attid = IVAL(in->value_ctr.values[i].blob->data, 0);
     1094
     1095                status = dsdb_schema_pfm_oid_from_attid(ctx->pfm_remote, attid,
     1096                                                        out->values, &oid);
     1097                if (!W_ERROR_IS_OK(status)) {
     1098                        DEBUG(0,(__location__ ": Error: Unknown ATTID 0x%08X\n",
     1099                                 attid));
     1100                        return status;
     1101                }
     1102
     1103                out->values[i] = data_blob_string_const(oid);
     1104        }
     1105
     1106        return WERR_OK;
     1107}
     1108
     1109static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
     1110                                                   const struct dsdb_attribute *attr,
     1111                                                   const struct ldb_message_element *in,
     1112                                                   TALLOC_CTX *mem_ctx,
     1113                                                   struct drsuapi_DsReplicaAttribute *out)
     1114{
     1115        unsigned int i;
    7181116        DATA_BLOB *blobs;
    7191117
    720         out->attid= attr->attributeID_id;
     1118        out->attid= dsdb_attribute_get_attid(attr,
     1119                                             ctx->is_schema_nc);
    7211120        out->value_ctr.num_values= in->num_values;
    7221121        out->value_ctr.values= talloc_array(mem_ctx,
     
    7301129        for (i=0; i < in->num_values; i++) {
    7311130                const struct dsdb_class *obj_class;
     1131                const struct dsdb_attribute *obj_attr;
     1132                struct ldb_val *v;
    7321133
    7331134                out->value_ctr.values[i].blob= &blobs[i];
     
    7361137                W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
    7371138
    738                 obj_class = dsdb_class_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
    739                 if (!obj_class) {
    740                         return WERR_FOOBAR;
    741                 }
    742                 SIVAL(blobs[i].data, 0, obj_class->governsID_id);
     1139                /* in DRS windows puts the classes in the opposite
     1140                   order to the order used in ldap */
     1141                v = &in->values[(in->num_values-1)-i];
     1142
     1143                if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
     1144                        SIVAL(blobs[i].data, 0, obj_class->governsID_id);
     1145                } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(ctx->schema, v))) {
     1146                        SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
     1147                } else {
     1148                        uint32_t attid;
     1149                        WERROR werr;
     1150                        werr = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
     1151                                                              (const char *)v->data,
     1152                                                              &attid);
     1153                        W_ERROR_NOT_OK_RETURN(werr);
     1154                        SIVAL(blobs[i].data, 0, attid);
     1155                }
     1156
    7431157        }
    7441158
     
    7471161}
    7481162
    749 static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(struct ldb_context *ldb,
    750                                                    const struct dsdb_schema *schema,
    751                                                    const struct dsdb_attribute *attr,
    752                                                    const struct ldb_message_element *in,
    753                                                    TALLOC_CTX *mem_ctx,
    754                                                    struct drsuapi_DsReplicaAttribute *out)
    755 {
    756         uint32_t i;
     1163static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
     1164                                                  const struct dsdb_attribute *attr,
     1165                                                  const struct ldb_message_element *in,
     1166                                                  TALLOC_CTX *mem_ctx,
     1167                                                  struct drsuapi_DsReplicaAttribute *out)
     1168{
     1169        unsigned int i;
    7571170        DATA_BLOB *blobs;
    7581171
    759         out->attid= attr->attributeID_id;
     1172        out->attid= dsdb_attribute_get_attid(attr,
     1173                                             ctx->is_schema_nc);
    7601174        out->value_ctr.num_values= in->num_values;
    7611175        out->value_ctr.values= talloc_array(mem_ctx,
     
    7681182
    7691183        for (i=0; i < in->num_values; i++) {
    770                 const struct dsdb_attribute *obj_attr;
     1184                const struct dsdb_class *obj_class;
    7711185
    7721186                out->value_ctr.values[i].blob= &blobs[i];
     
    7751189                W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
    7761190
    777                 obj_attr = dsdb_attribute_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
     1191                /* in DRS windows puts the classes in the opposite
     1192                   order to the order used in ldap */
     1193                obj_class = dsdb_class_by_lDAPDisplayName(ctx->schema,
     1194                                                          (const char *)in->values[(in->num_values-1)-i].data);
     1195                if (!obj_class) {
     1196                        return WERR_FOOBAR;
     1197                }
     1198                SIVAL(blobs[i].data, 0, obj_class->governsID_id);
     1199        }
     1200
     1201
     1202        return WERR_OK;
     1203}
     1204
     1205static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
     1206                                                   const struct dsdb_attribute *attr,
     1207                                                   const struct ldb_message_element *in,
     1208                                                   TALLOC_CTX *mem_ctx,
     1209                                                   struct drsuapi_DsReplicaAttribute *out)
     1210{
     1211        unsigned int i;
     1212        DATA_BLOB *blobs;
     1213
     1214        out->attid= dsdb_attribute_get_attid(attr,
     1215                                             ctx->is_schema_nc);
     1216        out->value_ctr.num_values= in->num_values;
     1217        out->value_ctr.values= talloc_array(mem_ctx,
     1218                                            struct drsuapi_DsAttributeValue,
     1219                                            in->num_values);
     1220        W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
     1221
     1222        blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
     1223        W_ERROR_HAVE_NO_MEMORY(blobs);
     1224
     1225        for (i=0; i < in->num_values; i++) {
     1226                const struct dsdb_attribute *obj_attr;
     1227
     1228                out->value_ctr.values[i].blob= &blobs[i];
     1229
     1230                blobs[i] = data_blob_talloc(blobs, NULL, 4);
     1231                W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
     1232
     1233                obj_attr = dsdb_attribute_by_lDAPDisplayName(ctx->schema, (const char *)in->values[i].data);
    7781234                if (!obj_attr) {
    7791235                        return WERR_FOOBAR;
     
    7861242}
    7871243
    788 static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
    789                                                   const struct dsdb_schema *schema,
     1244static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    7901245                                                  const struct dsdb_attribute *attr,
    7911246                                                  const struct ldb_message_element *in,
     
    7931248                                                  struct drsuapi_DsReplicaAttribute *out)
    7941249{
    795         uint32_t i;
     1250        unsigned int i;
    7961251        DATA_BLOB *blobs;
    7971252
    798         out->attid= attr->attributeID_id;
     1253        out->attid= dsdb_attribute_get_attid(attr,
     1254                                             ctx->is_schema_nc);
    7991255        out->value_ctr.num_values= in->num_values;
    8001256        out->value_ctr.values= talloc_array(mem_ctx,
     
    8071263
    8081264        for (i=0; i < in->num_values; i++) {
    809                 uint32_t v;
     1265                uint32_t attid;
    8101266                WERROR status;
    8111267
     
    8151271                W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
    8161272
    817                 status = dsdb_map_oid2int(schema,
    818                                           (const char *)in->values[i].data,
    819                                           &v);
     1273                status = dsdb_schema_pfm_attid_from_oid(ctx->schema->prefixmap,
     1274                                                        (const char *)in->values[i].data,
     1275                                                        &attid);
    8201276                W_ERROR_NOT_OK_RETURN(status);
    8211277
    822                 SIVAL(blobs[i].data, 0, v);
    823         }
    824 
    825         return WERR_OK;
    826 }
    827 
    828 static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb,
    829                                              const struct dsdb_schema *schema,
     1278                SIVAL(blobs[i].data, 0, attid);
     1279        }
     1280
     1281        return WERR_OK;
     1282}
     1283
     1284static WERROR dsdb_syntax_OID_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    8301285                                             const struct dsdb_attribute *attr,
    8311286                                             const struct drsuapi_DsReplicaAttribute *in,
     
    8331288                                             struct ldb_message_element *out)
    8341289{
    835         uint32_t i;
     1290        WERROR werr;
    8361291
    8371292        switch (attr->attributeID_id) {
    838         case DRSUAPI_ATTRIBUTE_objectClass:
    839         case DRSUAPI_ATTRIBUTE_subClassOf:
    840         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
    841         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
    842         case DRSUAPI_ATTRIBUTE_possSuperiors:
    843                 return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
    844         case DRSUAPI_ATTRIBUTE_systemMustContain:
    845         case DRSUAPI_ATTRIBUTE_systemMayContain:       
    846         case DRSUAPI_ATTRIBUTE_mustContain:
    847         case DRSUAPI_ATTRIBUTE_mayContain:
    848                 return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
    849         case DRSUAPI_ATTRIBUTE_governsID:
    850         case DRSUAPI_ATTRIBUTE_attributeID:
    851         case DRSUAPI_ATTRIBUTE_attributeSyntax:
    852                 return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
    853         }
    854 
    855         out->flags      = 0;
    856         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
    857         W_ERROR_HAVE_NO_MEMORY(out->name);
    858 
    859         out->num_values = in->value_ctr.num_values;
    860         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
    861         W_ERROR_HAVE_NO_MEMORY(out->values);
    862 
    863         for (i=0; i < out->num_values; i++) {
    864                 uint32_t v;
    865                 const char *name;
    866                 char *str;
    867 
    868                 if (in->value_ctr.values[i].blob == NULL) {
    869                         return WERR_FOOBAR;
    870                 }
    871 
    872                 if (in->value_ctr.values[i].blob->length != 4) {
    873                         return WERR_FOOBAR;
    874                 }
    875 
    876                 v = IVAL(in->value_ctr.values[i].blob->data, 0);
    877 
    878                 name = dsdb_lDAPDisplayName_by_id(schema, v);
    879                 if (!name) {
    880                         return WERR_FOOBAR;
    881                 }
    882 
    883                 str = talloc_strdup(out->values, name);
    884                 W_ERROR_HAVE_NO_MEMORY(str);
    885 
    886                 out->values[i] = data_blob_string_const(str);
    887         }
    888 
    889         return WERR_OK;
    890 }
    891 
    892 static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb,
    893                                              const struct dsdb_schema *schema,
     1293        case DRSUAPI_ATTID_objectClass:
     1294        case DRSUAPI_ATTID_subClassOf:
     1295        case DRSUAPI_ATTID_auxiliaryClass:
     1296        case DRSUAPI_ATTID_systemAuxiliaryClass:
     1297        case DRSUAPI_ATTID_systemPossSuperiors:
     1298        case DRSUAPI_ATTID_possSuperiors:
     1299                werr = _dsdb_syntax_OID_obj_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
     1300                break;
     1301        case DRSUAPI_ATTID_systemMustContain:
     1302        case DRSUAPI_ATTID_systemMayContain:
     1303        case DRSUAPI_ATTID_mustContain:
     1304        case DRSUAPI_ATTID_rDNAttId:
     1305        case DRSUAPI_ATTID_transportAddressAttribute:
     1306        case DRSUAPI_ATTID_mayContain:
     1307                werr = _dsdb_syntax_OID_attr_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
     1308                break;
     1309        case DRSUAPI_ATTID_governsID:
     1310        case DRSUAPI_ATTID_attributeID:
     1311        case DRSUAPI_ATTID_attributeSyntax:
     1312                werr = _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
     1313                break;
     1314        default:
     1315                DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
     1316                         attr->lDAPDisplayName));
     1317                return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
     1318        }
     1319
     1320        /* When we are doing the vampire of a schema, we don't want
     1321         * the inability to reference an OID to get in the way.
     1322         * Otherwise, we won't get the new schema with which to
     1323         * understand this */
     1324        if (!W_ERROR_IS_OK(werr) && ctx->schema->relax_OID_conversions) {
     1325                return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ctx, attr, in, mem_ctx, out);
     1326        }
     1327        return werr;
     1328}
     1329
     1330static WERROR dsdb_syntax_OID_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    8941331                                             const struct dsdb_attribute *attr,
    8951332                                             const struct ldb_message_element *in,
     
    8971334                                             struct drsuapi_DsReplicaAttribute *out)
    8981335{
    899         uint32_t i;
     1336        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     1337                return WERR_FOOBAR;
     1338        }
     1339
     1340        switch (attr->attributeID_id) {
     1341        case DRSUAPI_ATTID_objectClass:
     1342        case DRSUAPI_ATTID_subClassOf:
     1343        case DRSUAPI_ATTID_auxiliaryClass:
     1344        case DRSUAPI_ATTID_systemAuxiliaryClass:
     1345        case DRSUAPI_ATTID_systemPossSuperiors:
     1346        case DRSUAPI_ATTID_possSuperiors:
     1347                return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
     1348        case DRSUAPI_ATTID_systemMustContain:
     1349        case DRSUAPI_ATTID_systemMayContain:
     1350        case DRSUAPI_ATTID_mustContain:
     1351        case DRSUAPI_ATTID_rDNAttId:
     1352        case DRSUAPI_ATTID_transportAddressAttribute:
     1353        case DRSUAPI_ATTID_mayContain:
     1354                return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
     1355        case DRSUAPI_ATTID_governsID:
     1356        case DRSUAPI_ATTID_attributeID:
     1357        case DRSUAPI_ATTID_attributeSyntax:
     1358                return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
     1359        }
     1360
     1361        DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
     1362                 attr->lDAPDisplayName));
     1363
     1364        return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ctx, attr, in, mem_ctx, out);
     1365}
     1366
     1367static WERROR _dsdb_syntax_OID_validate_numericoid(const struct dsdb_syntax_ctx *ctx,
     1368                                                   const struct dsdb_attribute *attr,
     1369                                                   const struct ldb_message_element *in)
     1370{
     1371        unsigned int i;
     1372        TALLOC_CTX *tmp_ctx;
     1373
     1374        tmp_ctx = talloc_new(ctx->ldb);
     1375        W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
     1376
     1377        for (i=0; i < in->num_values; i++) {
     1378                DATA_BLOB blob;
     1379                char *oid_out;
     1380                const char *oid = (const char*)in->values[i].data;
     1381
     1382                if (!ber_write_OID_String(tmp_ctx, &blob, oid)) {
     1383                        DEBUG(0,("ber_write_OID_String() failed for %s\n", oid));
     1384                        talloc_free(tmp_ctx);
     1385                        return WERR_INVALID_PARAMETER;
     1386                }
     1387
     1388                if (!ber_read_OID_String(tmp_ctx, blob, &oid_out)) {
     1389                        DEBUG(0,("ber_read_OID_String() failed for %s\n",
     1390                                 hex_encode_talloc(tmp_ctx, blob.data, blob.length)));
     1391                        talloc_free(tmp_ctx);
     1392                        return WERR_INVALID_PARAMETER;
     1393                }
     1394
     1395                if (strcmp(oid, oid_out) != 0) {
     1396                        talloc_free(tmp_ctx);
     1397                        return WERR_INVALID_PARAMETER;
     1398                }
     1399        }
     1400
     1401        talloc_free(tmp_ctx);
     1402        return WERR_OK;
     1403}
     1404
     1405static WERROR dsdb_syntax_OID_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     1406                                           const struct dsdb_attribute *attr,
     1407                                           const struct ldb_message_element *in)
     1408{
     1409        WERROR status;
     1410        struct drsuapi_DsReplicaAttribute drs_tmp;
     1411        struct ldb_message_element ldb_tmp;
     1412        TALLOC_CTX *tmp_ctx;
     1413
     1414        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     1415                return WERR_FOOBAR;
     1416        }
     1417
     1418        switch (attr->attributeID_id) {
     1419        case DRSUAPI_ATTID_governsID:
     1420        case DRSUAPI_ATTID_attributeID:
     1421        case DRSUAPI_ATTID_attributeSyntax:
     1422                return _dsdb_syntax_OID_validate_numericoid(ctx, attr, in);
     1423        }
     1424
     1425        /*
     1426         * TODO: optimize and verify this code
     1427         */
     1428
     1429        tmp_ctx = talloc_new(ctx->ldb);
     1430        W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
     1431
     1432        status = dsdb_syntax_OID_ldb_to_drsuapi(ctx,
     1433                                                attr,
     1434                                                in,
     1435                                                tmp_ctx,
     1436                                                &drs_tmp);
     1437        if (!W_ERROR_IS_OK(status)) {
     1438                talloc_free(tmp_ctx);
     1439                return status;
     1440        }
     1441
     1442        status = dsdb_syntax_OID_drsuapi_to_ldb(ctx,
     1443                                                attr,
     1444                                                &drs_tmp,
     1445                                                tmp_ctx,
     1446                                                &ldb_tmp);
     1447        if (!W_ERROR_IS_OK(status)) {
     1448                talloc_free(tmp_ctx);
     1449                return status;
     1450        }
     1451
     1452        talloc_free(tmp_ctx);
     1453        return WERR_OK;
     1454}
     1455
     1456static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
     1457                                                 const struct dsdb_attribute *attr,
     1458                                                 const struct drsuapi_DsReplicaAttribute *in,
     1459                                                 TALLOC_CTX *mem_ctx,
     1460                                                 struct ldb_message_element *out)
     1461{
     1462        unsigned int i;
     1463
     1464        out->flags      = 0;
     1465        out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
     1466        W_ERROR_HAVE_NO_MEMORY(out->name);
     1467
     1468        out->num_values = in->value_ctr.num_values;
     1469        out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
     1470        W_ERROR_HAVE_NO_MEMORY(out->values);
     1471
     1472        for (i=0; i < out->num_values; i++) {
     1473                char *str;
     1474
     1475                if (in->value_ctr.values[i].blob == NULL) {
     1476                        return WERR_FOOBAR;
     1477                }
     1478
     1479                if (in->value_ctr.values[i].blob->length == 0) {
     1480                        return WERR_FOOBAR;
     1481                }
     1482
     1483                if (!convert_string_talloc(out->values,
     1484                                           CH_UTF16, CH_UNIX,
     1485                                           in->value_ctr.values[i].blob->data,
     1486                                           in->value_ctr.values[i].blob->length,
     1487                                           (void **)&str, NULL, false)) {
     1488                        return WERR_FOOBAR;
     1489                }
     1490
     1491                out->values[i] = data_blob_string_const(str);
     1492        }
     1493
     1494        return WERR_OK;
     1495}
     1496
     1497static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
     1498                                                 const struct dsdb_attribute *attr,
     1499                                                 const struct ldb_message_element *in,
     1500                                                 TALLOC_CTX *mem_ctx,
     1501                                                 struct drsuapi_DsReplicaAttribute *out)
     1502{
     1503        unsigned int i;
    9001504        DATA_BLOB *blobs;
    9011505
    902         if (attr->attributeID_id == 0xFFFFFFFF) {
    903                 return WERR_FOOBAR;
    904         }
    905 
    906         switch (attr->attributeID_id) {
    907         case DRSUAPI_ATTRIBUTE_objectClass:
    908         case DRSUAPI_ATTRIBUTE_subClassOf:
    909         case DRSUAPI_ATTRIBUTE_auxiliaryClass:
    910         case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
    911         case DRSUAPI_ATTRIBUTE_possSuperiors:
    912                 return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
    913         case DRSUAPI_ATTRIBUTE_systemMustContain:
    914         case DRSUAPI_ATTRIBUTE_systemMayContain:       
    915         case DRSUAPI_ATTRIBUTE_mustContain:
    916         case DRSUAPI_ATTRIBUTE_mayContain:
    917                 return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
    918         case DRSUAPI_ATTRIBUTE_governsID:
    919         case DRSUAPI_ATTRIBUTE_attributeID:
    920         case DRSUAPI_ATTRIBUTE_attributeSyntax:
    921                 return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
    922         }
    923 
    924         out->attid                      = attr->attributeID_id;
     1506        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     1507                return WERR_FOOBAR;
     1508        }
     1509
     1510        out->attid                      = dsdb_attribute_get_attid(attr,
     1511                                                                   ctx->is_schema_nc);
    9251512        out->value_ctr.num_values       = in->num_values;
    9261513        out->value_ctr.values           = talloc_array(mem_ctx,
     
    9331520
    9341521        for (i=0; i < in->num_values; i++) {
    935                 uint32_t v;
    936 
    9371522                out->value_ctr.values[i].blob   = &blobs[i];
    9381523
    939                 blobs[i] = data_blob_talloc(blobs, NULL, 4);
    940                 W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
    941 
    942                 v = strtol((const char *)in->values[i].data, NULL, 10);
    943 
    944                 SIVAL(blobs[i].data, 0, v);
    945         }
    946 
    947         return WERR_OK;
    948 }
    949 
    950 static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb,
    951                                                  const struct dsdb_schema *schema,
    952                                                  const struct dsdb_attribute *attr,
    953                                                  const struct drsuapi_DsReplicaAttribute *in,
    954                                                  TALLOC_CTX *mem_ctx,
    955                                                  struct ldb_message_element *out)
    956 {
    957         uint32_t i;
     1524                if (!convert_string_talloc(blobs,
     1525                                           CH_UNIX, CH_UTF16,
     1526                                           in->values[i].data, in->values[i].length,
     1527                                           (void **)&blobs[i].data, &blobs[i].length, false)) {
     1528                        return WERR_FOOBAR;
     1529                }
     1530        }
     1531
     1532        return WERR_OK;
     1533}
     1534
     1535static WERROR dsdb_syntax_UNICODE_validate_one_val(const struct dsdb_syntax_ctx *ctx,
     1536                                                   const struct dsdb_attribute *attr,
     1537                                                   const struct ldb_val *val)
     1538{
     1539        void *dst = NULL;
     1540        size_t size;
     1541        bool ok;
     1542
     1543        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     1544                return WERR_FOOBAR;
     1545        }
     1546
     1547        ok = convert_string_talloc(ctx->ldb,
     1548                                   CH_UNIX, CH_UTF16,
     1549                                   val->data,
     1550                                   val->length,
     1551                                   (void **)&dst,
     1552                                   &size, false);
     1553        TALLOC_FREE(dst);
     1554        if (!ok) {
     1555                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1556        }
     1557
     1558        if (attr->rangeLower) {
     1559                if ((size/2) < *attr->rangeLower) {
     1560                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1561                }
     1562        }
     1563
     1564        if (attr->rangeUpper) {
     1565                if ((size/2) > *attr->rangeUpper) {
     1566                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1567                }
     1568        }
     1569
     1570        return WERR_OK;
     1571}
     1572
     1573static WERROR dsdb_syntax_UNICODE_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     1574                                               const struct dsdb_attribute *attr,
     1575                                               const struct ldb_message_element *in)
     1576{
     1577        WERROR status;
     1578        unsigned int i;
     1579
     1580        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     1581                return WERR_FOOBAR;
     1582        }
     1583
     1584        for (i=0; i < in->num_values; i++) {
     1585                if (in->values[i].length == 0) {
     1586                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1587                }
     1588
     1589                status = dsdb_syntax_UNICODE_validate_one_val(ctx,
     1590                                                              attr,
     1591                                                              &in->values[i]);
     1592                if (!W_ERROR_IS_OK(status)) {
     1593                        return status;
     1594                }
     1595        }
     1596
     1597        return WERR_OK;
     1598}
     1599
     1600static WERROR dsdb_syntax_one_DN_drsuapi_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
     1601                                                const struct dsdb_syntax *syntax,
     1602                                                const DATA_BLOB *in, DATA_BLOB *out)
     1603{
     1604        struct drsuapi_DsReplicaObjectIdentifier3 id3;
     1605        enum ndr_err_code ndr_err;
     1606        DATA_BLOB guid_blob;
     1607        struct ldb_dn *dn;
     1608        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     1609        int ret;
     1610        NTSTATUS status;
     1611
     1612        if (!tmp_ctx) {
     1613                W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
     1614        }
     1615
     1616        if (in == NULL) {
     1617                talloc_free(tmp_ctx);
     1618                return WERR_FOOBAR;
     1619        }
     1620
     1621        if (in->length == 0) {
     1622                talloc_free(tmp_ctx);
     1623                return WERR_FOOBAR;
     1624        }
     1625
     1626
     1627        /* windows sometimes sends an extra two pad bytes here */
     1628        ndr_err = ndr_pull_struct_blob(in,
     1629                                       tmp_ctx, &id3,
     1630                                       (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
     1631        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     1632                status = ndr_map_error2ntstatus(ndr_err);
     1633                talloc_free(tmp_ctx);
     1634                return ntstatus_to_werror(status);
     1635        }
     1636
     1637        dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
     1638        if (!dn) {
     1639                talloc_free(tmp_ctx);
     1640                /* If this fails, it must be out of memory, as it does not do much parsing */
     1641                W_ERROR_HAVE_NO_MEMORY(dn);
     1642        }
     1643
     1644        if (!GUID_all_zero(&id3.guid)) {
     1645                status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
     1646                if (!NT_STATUS_IS_OK(status)) {
     1647                        talloc_free(tmp_ctx);
     1648                        return ntstatus_to_werror(status);
     1649                }
     1650
     1651                ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
     1652                if (ret != LDB_SUCCESS) {
     1653                        talloc_free(tmp_ctx);
     1654                        return WERR_FOOBAR;
     1655                }
     1656                talloc_free(guid_blob.data);
     1657        }
     1658
     1659        if (id3.__ndr_size_sid) {
     1660                DATA_BLOB sid_blob;
     1661                ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
     1662                                               (ndr_push_flags_fn_t)ndr_push_dom_sid);
     1663                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     1664                        status = ndr_map_error2ntstatus(ndr_err);
     1665                        talloc_free(tmp_ctx);
     1666                        return ntstatus_to_werror(status);
     1667                }
     1668
     1669                ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
     1670                if (ret != LDB_SUCCESS) {
     1671                        talloc_free(tmp_ctx);
     1672                        return WERR_FOOBAR;
     1673                }
     1674        }
     1675
     1676        *out = data_blob_string_const(ldb_dn_get_extended_linearized(mem_ctx, dn, 1));
     1677        talloc_free(tmp_ctx);
     1678        return WERR_OK;
     1679}
     1680
     1681static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
     1682                                            const struct dsdb_attribute *attr,
     1683                                            const struct drsuapi_DsReplicaAttribute *in,
     1684                                            TALLOC_CTX *mem_ctx,
     1685                                            struct ldb_message_element *out)
     1686{
     1687        unsigned int i;
    9581688
    9591689        out->flags      = 0;
     
    9661696
    9671697        for (i=0; i < out->num_values; i++) {
    968                 char *str;
    969 
    970                 if (in->value_ctr.values[i].blob == NULL) {
    971                         return WERR_FOOBAR;
    972                 }
    973 
    974                 if (in->value_ctr.values[i].blob->length == 0) {
    975                         return WERR_FOOBAR;
    976                 }
    977 
    978                 if (!convert_string_talloc_convenience(out->values,
    979                                                 schema->iconv_convenience,
    980                                                                         CH_UTF16, CH_UNIX,
    981                                             in->value_ctr.values[i].blob->data,
    982                                             in->value_ctr.values[i].blob->length,
    983                                             (void **)&str, NULL, false)) {
    984                         return WERR_FOOBAR;
    985                 }
    986 
    987                 out->values[i] = data_blob_string_const(str);
    988         }
    989 
    990         return WERR_OK;
    991 }
    992 
    993 static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb,
    994                                                  const struct dsdb_schema *schema,
    995                                                  const struct dsdb_attribute *attr,
    996                                                  const struct ldb_message_element *in,
    997                                                  TALLOC_CTX *mem_ctx,
    998                                                  struct drsuapi_DsReplicaAttribute *out)
    999 {
    1000         uint32_t i;
     1698                WERROR status = dsdb_syntax_one_DN_drsuapi_to_ldb(out->values, ctx->ldb, attr->syntax,
     1699                                                                  in->value_ctr.values[i].blob,
     1700                                                                  &out->values[i]);
     1701                if (!W_ERROR_IS_OK(status)) {
     1702                        return status;
     1703                }
     1704
     1705        }
     1706
     1707        return WERR_OK;
     1708}
     1709
     1710static WERROR dsdb_syntax_DN_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
     1711                                            const struct dsdb_attribute *attr,
     1712                                            const struct ldb_message_element *in,
     1713                                            TALLOC_CTX *mem_ctx,
     1714                                            struct drsuapi_DsReplicaAttribute *out)
     1715{
     1716        unsigned int i;
    10011717        DATA_BLOB *blobs;
    10021718
    1003         if (attr->attributeID_id == 0xFFFFFFFF) {
    1004                 return WERR_FOOBAR;
    1005         }
    1006 
    1007         out->attid                      = attr->attributeID_id;
     1719        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     1720                return WERR_FOOBAR;
     1721        }
     1722
     1723        out->attid                      = dsdb_attribute_get_attid(attr,
     1724                                                                   ctx->is_schema_nc);
    10081725        out->value_ctr.num_values       = in->num_values;
    10091726        out->value_ctr.values           = talloc_array(mem_ctx,
     
    10161733
    10171734        for (i=0; i < in->num_values; i++) {
     1735                struct drsuapi_DsReplicaObjectIdentifier3 id3;
     1736                enum ndr_err_code ndr_err;
     1737                struct ldb_dn *dn;
     1738                TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     1739                NTSTATUS status;
     1740
     1741                W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
     1742
    10181743                out->value_ctr.values[i].blob   = &blobs[i];
    10191744
    1020                 if (!convert_string_talloc_convenience(blobs,
    1021                         schema->iconv_convenience, CH_UNIX, CH_UTF16,
    1022                         in->values[i].data, in->values[i].length,
    1023                         (void **)&blobs[i].data, &blobs[i].length, false)) {
    1024                                 return WERR_FOOBAR;
    1025                 }
    1026         }
    1027 
    1028         return WERR_OK;
    1029 }
    1030 
    1031 static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb,
    1032                                             const struct dsdb_schema *schema,
    1033                                             const struct dsdb_attribute *attr,
    1034                                             const struct drsuapi_DsReplicaAttribute *in,
    1035                                             TALLOC_CTX *mem_ctx,
    1036                                             struct ldb_message_element *out)
    1037 {
    1038         uint32_t i;
     1745                dn = ldb_dn_from_ldb_val(tmp_ctx, ctx->ldb, &in->values[i]);
     1746
     1747                W_ERROR_HAVE_NO_MEMORY(dn);
     1748
     1749                ZERO_STRUCT(id3);
     1750
     1751                status = dsdb_get_extended_dn_guid(dn, &id3.guid, "GUID");
     1752                if (!NT_STATUS_IS_OK(status) &&
     1753                    !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     1754                        talloc_free(tmp_ctx);
     1755                        return ntstatus_to_werror(status);
     1756                }
     1757
     1758                status = dsdb_get_extended_dn_sid(dn, &id3.sid, "SID");
     1759                if (!NT_STATUS_IS_OK(status) &&
     1760                    !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     1761                        talloc_free(tmp_ctx);
     1762                        return ntstatus_to_werror(status);
     1763                }
     1764
     1765                id3.dn = ldb_dn_get_linearized(dn);
     1766
     1767                ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
     1768                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     1769                        status = ndr_map_error2ntstatus(ndr_err);
     1770                        talloc_free(tmp_ctx);
     1771                        return ntstatus_to_werror(status);
     1772                }
     1773                talloc_free(tmp_ctx);
     1774        }
     1775
     1776        return WERR_OK;
     1777}
     1778
     1779static WERROR dsdb_syntax_DN_validate_one_val(const struct dsdb_syntax_ctx *ctx,
     1780                                              const struct dsdb_attribute *attr,
     1781                                              const struct ldb_val *val,
     1782                                              TALLOC_CTX *mem_ctx,
     1783                                              struct dsdb_dn **_dsdb_dn)
     1784{
     1785        static const char * const extended_list[] = { "GUID", "SID", NULL };
     1786        enum ndr_err_code ndr_err;
     1787        struct GUID guid;
     1788        struct dom_sid sid;
     1789        const DATA_BLOB *sid_blob;
     1790        struct dsdb_dn *dsdb_dn;
     1791        struct ldb_dn *dn;
     1792        char *dn_str;
     1793        struct ldb_dn *dn2;
     1794        char *dn2_str;
     1795        int num_components;
     1796        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     1797        NTSTATUS status;
     1798
     1799        W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
     1800
     1801        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     1802                return WERR_FOOBAR;
     1803        }
     1804
     1805        dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, val,
     1806                                attr->syntax->ldap_oid);
     1807        if (!dsdb_dn) {
     1808                talloc_free(tmp_ctx);
     1809                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1810        }
     1811        dn = dsdb_dn->dn;
     1812
     1813        dn2 = ldb_dn_copy(tmp_ctx, dn);
     1814        if (dn == NULL) {
     1815                talloc_free(tmp_ctx);
     1816                return WERR_NOMEM;
     1817        }
     1818
     1819        num_components = ldb_dn_get_comp_num(dn);
     1820
     1821        status = dsdb_get_extended_dn_guid(dn, &guid, "GUID");
     1822        if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     1823                num_components++;
     1824        } else if (!NT_STATUS_IS_OK(status)) {
     1825                talloc_free(tmp_ctx);
     1826                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1827        }
     1828
     1829        sid_blob = ldb_dn_get_extended_component(dn, "SID");
     1830        if (sid_blob) {
     1831                num_components++;
     1832                ndr_err = ndr_pull_struct_blob_all(sid_blob,
     1833                                                   tmp_ctx,
     1834                                                   &sid,
     1835                                                   (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
     1836                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     1837                        talloc_free(tmp_ctx);
     1838                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1839                }
     1840        }
     1841
     1842        /* Do not allow links to the RootDSE */
     1843        if (num_components == 0) {
     1844                talloc_free(tmp_ctx);
     1845                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1846        }
     1847
     1848        /*
     1849         * We need to check that only "GUID" and "SID" are
     1850         * specified as extended components, we do that
     1851         * by comparing the dn's after removing all components
     1852         * from one dn and only the allowed subset from the other
     1853         * one.
     1854         */
     1855        ldb_dn_extended_filter(dn, extended_list);
     1856
     1857        dn_str = ldb_dn_get_extended_linearized(tmp_ctx, dn, 0);
     1858        if (dn_str == NULL) {
     1859                talloc_free(tmp_ctx);
     1860                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1861        }
     1862        dn2_str = ldb_dn_get_extended_linearized(tmp_ctx, dn2, 0);
     1863        if (dn2_str == NULL) {
     1864                talloc_free(tmp_ctx);
     1865                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1866        }
     1867
     1868        if (strcmp(dn_str, dn2_str) != 0) {
     1869                talloc_free(tmp_ctx);
     1870                return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1871        }
     1872
     1873        *_dsdb_dn = talloc_move(mem_ctx, &dsdb_dn);
     1874        talloc_free(tmp_ctx);
     1875        return WERR_OK;
     1876}
     1877
     1878static WERROR dsdb_syntax_DN_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     1879                                          const struct dsdb_attribute *attr,
     1880                                          const struct ldb_message_element *in)
     1881{
     1882        unsigned int i;
     1883
     1884        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     1885                return WERR_FOOBAR;
     1886        }
     1887
     1888        for (i=0; i < in->num_values; i++) {
     1889                WERROR status;
     1890                struct dsdb_dn *dsdb_dn;
     1891                TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
     1892                W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
     1893
     1894                status = dsdb_syntax_DN_validate_one_val(ctx,
     1895                                                         attr,
     1896                                                         &in->values[i],
     1897                                                         tmp_ctx, &dsdb_dn);
     1898                if (!W_ERROR_IS_OK(status)) {
     1899                        talloc_free(tmp_ctx);
     1900                        return status;
     1901                }
     1902
     1903                if (dsdb_dn->dn_format != DSDB_NORMAL_DN) {
     1904                        talloc_free(tmp_ctx);
     1905                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     1906                }
     1907
     1908                talloc_free(tmp_ctx);
     1909        }
     1910
     1911        return WERR_OK;
     1912}
     1913
     1914static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
     1915                                                   const struct dsdb_attribute *attr,
     1916                                                   const struct drsuapi_DsReplicaAttribute *in,
     1917                                                   TALLOC_CTX *mem_ctx,
     1918                                                   struct ldb_message_element *out)
     1919{
     1920        unsigned int i;
    10391921        int ret;
    10401922
     
    10481930
    10491931        for (i=0; i < out->num_values; i++) {
    1050                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
     1932                struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
    10511933                enum ndr_err_code ndr_err;
    10521934                DATA_BLOB guid_blob;
    10531935                struct ldb_dn *dn;
     1936                struct dsdb_dn *dsdb_dn;
     1937                NTSTATUS status;
    10541938                TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    10551939                if (!tmp_ctx) {
     
    10671951                }
    10681952
    1069                
     1953
    10701954                /* windows sometimes sends an extra two pad bytes here */
    10711955                ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
    1072                                                tmp_ctx, schema->iconv_convenience, &id3,
    1073                                                (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
     1956                                               tmp_ctx, &id3,
     1957                                               (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
    10741958                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1075                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     1959                        status = ndr_map_error2ntstatus(ndr_err);
    10761960                        talloc_free(tmp_ctx);
    10771961                        return ntstatus_to_werror(status);
    10781962                }
    10791963
    1080                 dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
     1964                dn = ldb_dn_new(tmp_ctx, ctx->ldb, id3.dn);
    10811965                if (!dn) {
    10821966                        talloc_free(tmp_ctx);
     
    10851969                }
    10861970
    1087                 ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid,
    1088                                                (ndr_push_flags_fn_t)ndr_push_GUID);
    1089                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1090                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     1971                status = GUID_to_ndr_blob(&id3.guid, tmp_ctx, &guid_blob);
     1972                if (!NT_STATUS_IS_OK(status)) {
    10911973                        talloc_free(tmp_ctx);
    10921974                        return ntstatus_to_werror(status);
     
    11031985                if (id3.__ndr_size_sid) {
    11041986                        DATA_BLOB sid_blob;
    1105                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
     1987                        ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &id3.sid,
    11061988                                                       (ndr_push_flags_fn_t)ndr_push_dom_sid);
    11071989                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1108                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     1990                                status = ndr_map_error2ntstatus(ndr_err);
    11091991                                talloc_free(tmp_ctx);
    11101992                                return ntstatus_to_werror(status);
     
    11182000                }
    11192001
    1120                 out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1));
     2002                /* set binary stuff */
     2003                dsdb_dn = dsdb_dn_construct(tmp_ctx, dn, id3.binary, attr->syntax->ldap_oid);
     2004                if (!dsdb_dn) {
     2005                        /* If this fails, it must be out of memory, we know the ldap_oid is valid */
     2006                        talloc_free(tmp_ctx);
     2007                        W_ERROR_HAVE_NO_MEMORY(dsdb_dn);
     2008                }
     2009                out->values[i] = data_blob_string_const(dsdb_dn_get_extended_linearized(out->values, dsdb_dn, 1));
    11212010                talloc_free(tmp_ctx);
    11222011        }
     
    11252014}
    11262015
    1127 static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb,
    1128                                             const struct dsdb_schema *schema,
    1129                                             const struct dsdb_attribute *attr,
    1130                                             const struct ldb_message_element *in,
    1131                                             TALLOC_CTX *mem_ctx,
    1132                                             struct drsuapi_DsReplicaAttribute *out)
    1133 {
    1134         uint32_t i;
     2016static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
     2017                                                   const struct dsdb_attribute *attr,
     2018                                                   const struct ldb_message_element *in,
     2019                                                   TALLOC_CTX *mem_ctx,
     2020                                                   struct drsuapi_DsReplicaAttribute *out)
     2021{
     2022        unsigned int i;
    11352023        DATA_BLOB *blobs;
    11362024
    1137         if (attr->attributeID_id == 0xFFFFFFFF) {
    1138                 return WERR_FOOBAR;
    1139         }
    1140 
    1141         out->attid                      = attr->attributeID_id;
     2025        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     2026                return WERR_FOOBAR;
     2027        }
     2028
     2029        out->attid                      = dsdb_attribute_get_attid(attr,
     2030                                                                   ctx->is_schema_nc);
    11422031        out->value_ctr.num_values       = in->num_values;
    11432032        out->value_ctr.values           = talloc_array(mem_ctx,
     
    11502039
    11512040        for (i=0; i < in->num_values; i++) {
    1152                 struct drsuapi_DsReplicaObjectIdentifier3 id3;
     2041                struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
    11532042                enum ndr_err_code ndr_err;
    1154                 const DATA_BLOB *guid_blob, *sid_blob;
    1155                 struct ldb_dn *dn;
     2043                const DATA_BLOB *sid_blob;
     2044                struct dsdb_dn *dsdb_dn;
    11562045                TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     2046                NTSTATUS status;
     2047
    11572048                W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
    11582049
    11592050                out->value_ctr.values[i].blob   = &blobs[i];
    11602051
    1161                 dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
    1162 
    1163                 W_ERROR_HAVE_NO_MEMORY(dn);
    1164 
    1165                 guid_blob = ldb_dn_get_extended_component(dn, "GUID");
     2052                dsdb_dn = dsdb_dn_parse(tmp_ctx, ctx->ldb, &in->values[i], attr->syntax->ldap_oid);
     2053
     2054                if (!dsdb_dn) {
     2055                        talloc_free(tmp_ctx);
     2056                        return ntstatus_to_werror(NT_STATUS_INVALID_PARAMETER);
     2057                }
    11662058
    11672059                ZERO_STRUCT(id3);
    11682060
    1169                 if (guid_blob) {
    1170                         ndr_err = ndr_pull_struct_blob_all(guid_blob,
    1171                                                            tmp_ctx, schema->iconv_convenience, &id3.guid,
    1172                                                            (ndr_pull_flags_fn_t)ndr_pull_GUID);
     2061                status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &id3.guid, "GUID");
     2062                if (!NT_STATUS_IS_OK(status) &&
     2063                    !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     2064                        talloc_free(tmp_ctx);
     2065                        return ntstatus_to_werror(status);
     2066                }
     2067
     2068                sid_blob = ldb_dn_get_extended_component(dsdb_dn->dn, "SID");
     2069                if (sid_blob) {
     2070
     2071                        ndr_err = ndr_pull_struct_blob_all(sid_blob,
     2072                                                           tmp_ctx, &id3.sid,
     2073                                                           (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
    11732074                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1174                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     2075                                status = ndr_map_error2ntstatus(ndr_err);
    11752076                                talloc_free(tmp_ctx);
    11762077                                return ntstatus_to_werror(status);
     
    11782079                }
    11792080
    1180                 sid_blob = ldb_dn_get_extended_component(dn, "SID");
    1181                 if (sid_blob) {
    1182                        
    1183                         ndr_err = ndr_pull_struct_blob_all(sid_blob,
    1184                                                            tmp_ctx, schema->iconv_convenience, &id3.sid,
    1185                                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
    1186                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1187                                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    1188                                 talloc_free(tmp_ctx);
    1189                                 return ntstatus_to_werror(status);
    1190                         }
    1191                 }
    1192 
    1193                 id3.dn = ldb_dn_get_linearized(dn);
    1194 
    1195                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
     2081                id3.dn = ldb_dn_get_linearized(dsdb_dn->dn);
     2082
     2083                /* get binary stuff */
     2084                id3.binary = dsdb_dn->extra_part;
     2085
     2086                ndr_err = ndr_push_struct_blob(&blobs[i], blobs, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
    11962087                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1197                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     2088                        status = ndr_map_error2ntstatus(ndr_err);
    11982089                        talloc_free(tmp_ctx);
    11992090                        return ntstatus_to_werror(status);
     
    12052096}
    12062097
    1207 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb,
    1208                                                    const struct dsdb_schema *schema,
     2098static WERROR dsdb_syntax_DN_BINARY_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     2099                                                 const struct dsdb_attribute *attr,
     2100                                                 const struct ldb_message_element *in)
     2101{
     2102        unsigned int i;
     2103
     2104        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     2105                return WERR_FOOBAR;
     2106        }
     2107
     2108        for (i=0; i < in->num_values; i++) {
     2109                WERROR status;
     2110                struct dsdb_dn *dsdb_dn;
     2111                TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
     2112                W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
     2113
     2114                status = dsdb_syntax_DN_validate_one_val(ctx,
     2115                                                         attr,
     2116                                                         &in->values[i],
     2117                                                         tmp_ctx, &dsdb_dn);
     2118                if (!W_ERROR_IS_OK(status)) {
     2119                        talloc_free(tmp_ctx);
     2120                        return status;
     2121                }
     2122
     2123                if (dsdb_dn->dn_format != DSDB_BINARY_DN) {
     2124                        talloc_free(tmp_ctx);
     2125                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     2126                }
     2127
     2128                status = dsdb_syntax_DATA_BLOB_validate_one_val(ctx,
     2129                                                                attr,
     2130                                                                &dsdb_dn->extra_part);
     2131                if (!W_ERROR_IS_OK(status)) {
     2132                        talloc_free(tmp_ctx);
     2133                        return status;
     2134                }
     2135
     2136                talloc_free(tmp_ctx);
     2137        }
     2138
     2139        return WERR_OK;
     2140}
     2141
     2142static WERROR dsdb_syntax_DN_STRING_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
    12092143                                                   const struct dsdb_attribute *attr,
    12102144                                                   const struct drsuapi_DsReplicaAttribute *in,
     
    12122146                                                   struct ldb_message_element *out)
    12132147{
    1214         uint32_t i;
    1215 
    1216         out->flags      = 0;
    1217         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
    1218         W_ERROR_HAVE_NO_MEMORY(out->name);
    1219 
    1220         out->num_values = in->value_ctr.num_values;
    1221         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
    1222         W_ERROR_HAVE_NO_MEMORY(out->values);
    1223 
    1224         for (i=0; i < out->num_values; i++) {
    1225                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
    1226                 char *binary;
    1227                 char *str;
    1228                 enum ndr_err_code ndr_err;
    1229 
    1230                 if (in->value_ctr.values[i].blob == NULL) {
    1231                         return WERR_FOOBAR;
    1232                 }
    1233 
    1234                 if (in->value_ctr.values[i].blob->length == 0) {
    1235                         return WERR_FOOBAR;
    1236                 }
    1237 
    1238                 ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
    1239                                                    out->values, schema->iconv_convenience, &id3b,
    1240                                                    (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
    1241                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1242                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    1243                         return ntstatus_to_werror(status);
    1244                 }
    1245 
    1246                 /* TODO: handle id3.guid and id3.sid */
    1247                 binary = data_blob_hex_string(out->values, &id3b.binary);
    1248                 W_ERROR_HAVE_NO_MEMORY(binary);
    1249 
    1250                 str = talloc_asprintf(out->values, "B:%u:%s:%s",
    1251                                       (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */
    1252                                       binary,
    1253                                       id3b.dn);
    1254                 W_ERROR_HAVE_NO_MEMORY(str);
    1255 
    1256                 /* TODO: handle id3.guid and id3.sid */
    1257                 out->values[i] = data_blob_string_const(str);
    1258         }
    1259 
    1260         return WERR_OK;
    1261 }
    1262 
    1263 static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb,
    1264                                                    const struct dsdb_schema *schema,
     2148        return dsdb_syntax_DN_BINARY_drsuapi_to_ldb(ctx,
     2149                                                    attr,
     2150                                                    in,
     2151                                                    mem_ctx,
     2152                                                    out);
     2153}
     2154
     2155static WERROR dsdb_syntax_DN_STRING_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
    12652156                                                   const struct dsdb_attribute *attr,
    12662157                                                   const struct ldb_message_element *in,
     
    12682159                                                   struct drsuapi_DsReplicaAttribute *out)
    12692160{
    1270         uint32_t i;
     2161        return dsdb_syntax_DN_BINARY_ldb_to_drsuapi(ctx,
     2162                                                    attr,
     2163                                                    in,
     2164                                                    mem_ctx,
     2165                                                    out);
     2166}
     2167
     2168static WERROR dsdb_syntax_DN_STRING_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     2169                                                 const struct dsdb_attribute *attr,
     2170                                                 const struct ldb_message_element *in)
     2171{
     2172        unsigned int i;
     2173
     2174        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     2175                return WERR_FOOBAR;
     2176        }
     2177
     2178        for (i=0; i < in->num_values; i++) {
     2179                WERROR status;
     2180                struct dsdb_dn *dsdb_dn;
     2181                TALLOC_CTX *tmp_ctx = talloc_new(ctx->ldb);
     2182                W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
     2183
     2184                status = dsdb_syntax_DN_validate_one_val(ctx,
     2185                                                         attr,
     2186                                                         &in->values[i],
     2187                                                         tmp_ctx, &dsdb_dn);
     2188                if (!W_ERROR_IS_OK(status)) {
     2189                        talloc_free(tmp_ctx);
     2190                        return status;
     2191                }
     2192
     2193                if (dsdb_dn->dn_format != DSDB_STRING_DN) {
     2194                        talloc_free(tmp_ctx);
     2195                        return WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     2196                }
     2197
     2198                status = dsdb_syntax_UNICODE_validate_one_val(ctx,
     2199                                                              attr,
     2200                                                              &dsdb_dn->extra_part);
     2201                if (!W_ERROR_IS_OK(status)) {
     2202                        talloc_free(tmp_ctx);
     2203                        return status;
     2204                }
     2205
     2206                talloc_free(tmp_ctx);
     2207        }
     2208
     2209        return WERR_OK;
     2210}
     2211
     2212static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(const struct dsdb_syntax_ctx *ctx,
     2213                                                              const struct dsdb_attribute *attr,
     2214                                                              const struct drsuapi_DsReplicaAttribute *in,
     2215                                                              TALLOC_CTX *mem_ctx,
     2216                                                              struct ldb_message_element *out)
     2217{
     2218        unsigned int i;
     2219
     2220        out->flags      = 0;
     2221        out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
     2222        W_ERROR_HAVE_NO_MEMORY(out->name);
     2223
     2224        out->num_values = in->value_ctr.num_values;
     2225        out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
     2226        W_ERROR_HAVE_NO_MEMORY(out->values);
     2227
     2228        for (i=0; i < out->num_values; i++) {
     2229                size_t len;
     2230                char *str;
     2231
     2232                if (in->value_ctr.values[i].blob == NULL) {
     2233                        return WERR_FOOBAR;
     2234                }
     2235
     2236                if (in->value_ctr.values[i].blob->length < 4) {
     2237                        return WERR_FOOBAR;
     2238                }
     2239
     2240                len = IVAL(in->value_ctr.values[i].blob->data, 0);
     2241
     2242                if (len != in->value_ctr.values[i].blob->length) {
     2243                        return WERR_FOOBAR;
     2244                }
     2245
     2246                if (!convert_string_talloc(out->values, CH_UTF16, CH_UNIX,
     2247                                           in->value_ctr.values[i].blob->data+4,
     2248                                           in->value_ctr.values[i].blob->length-4,
     2249                                           (void **)&str, NULL, false)) {
     2250                        return WERR_FOOBAR;
     2251                }
     2252
     2253                out->values[i] = data_blob_string_const(str);
     2254        }
     2255
     2256        return WERR_OK;
     2257}
     2258
     2259static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_syntax_ctx *ctx,
     2260                                                              const struct dsdb_attribute *attr,
     2261                                                              const struct ldb_message_element *in,
     2262                                                              TALLOC_CTX *mem_ctx,
     2263                                                              struct drsuapi_DsReplicaAttribute *out)
     2264{
     2265        unsigned int i;
    12712266        DATA_BLOB *blobs;
    12722267
    1273         if (attr->attributeID_id == 0xFFFFFFFF) {
    1274                 return WERR_FOOBAR;
    1275         }
    1276 
    1277         out->attid                      = attr->attributeID_id;
     2268        if (attr->attributeID_id == DRSUAPI_ATTID_INVALID) {
     2269                return WERR_FOOBAR;
     2270        }
     2271
     2272        out->attid                      = dsdb_attribute_get_attid(attr,
     2273                                                                   ctx->is_schema_nc);
    12782274        out->value_ctr.num_values       = in->num_values;
    12792275        out->value_ctr.values           = talloc_array(mem_ctx,
     
    12862282
    12872283        for (i=0; i < in->num_values; i++) {
    1288                 struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
    1289                 enum ndr_err_code ndr_err;
    1290 
    1291                 out->value_ctr.values[i].blob   = &blobs[i];
    1292 
    1293                 /* TODO: handle id3b.guid and id3b.sid, id3.binary */
    1294                 ZERO_STRUCT(id3b);
    1295                 id3b.dn         = (const char *)in->values[i].data;
    1296                 id3b.binary     = data_blob(NULL, 0);
    1297 
    1298                 ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b,
    1299                                                (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
    1300                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1301                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    1302                         return ntstatus_to_werror(status);
    1303                 }
    1304         }
    1305 
    1306         return WERR_OK;
    1307 }
    1308 
    1309 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb,
    1310                                                               const struct dsdb_schema *schema,
    1311                                                               const struct dsdb_attribute *attr,
    1312                                                               const struct drsuapi_DsReplicaAttribute *in,
    1313                                                               TALLOC_CTX *mem_ctx,
    1314                                                               struct ldb_message_element *out)
    1315 {
    1316         uint32_t i;
    1317 
    1318         out->flags      = 0;
    1319         out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
    1320         W_ERROR_HAVE_NO_MEMORY(out->name);
    1321 
    1322         out->num_values = in->value_ctr.num_values;
    1323         out->values     = talloc_array(mem_ctx, struct ldb_val, out->num_values);
    1324         W_ERROR_HAVE_NO_MEMORY(out->values);
    1325 
    1326         for (i=0; i < out->num_values; i++) {
    1327                 uint32_t len;
    1328                 char *str;
    1329 
    1330                 if (in->value_ctr.values[i].blob == NULL) {
    1331                         return WERR_FOOBAR;
    1332                 }
    1333 
    1334                 if (in->value_ctr.values[i].blob->length < 4) {
    1335                         return WERR_FOOBAR;
    1336                 }
    1337 
    1338                 len = IVAL(in->value_ctr.values[i].blob->data, 0);
    1339 
    1340                 if (len != in->value_ctr.values[i].blob->length) {
    1341                         return WERR_FOOBAR;
    1342                 }
    1343 
    1344                 if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
    1345                                             in->value_ctr.values[i].blob->data+4,
    1346                                             in->value_ctr.values[i].blob->length-4,
    1347                                             (void **)&str, NULL, false)) {
    1348                         return WERR_FOOBAR;
    1349                 }
    1350 
    1351                 out->values[i] = data_blob_string_const(str);
    1352         }
    1353 
    1354         return WERR_OK;
    1355 }
    1356 
    1357 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb,
    1358                                                               const struct dsdb_schema *schema,
    1359                                                               const struct dsdb_attribute *attr,
    1360                                                               const struct ldb_message_element *in,
    1361                                                               TALLOC_CTX *mem_ctx,
    1362                                                               struct drsuapi_DsReplicaAttribute *out)
    1363 {
    1364         uint32_t i;
    1365         DATA_BLOB *blobs;
    1366 
    1367         if (attr->attributeID_id == 0xFFFFFFFF) {
    1368                 return WERR_FOOBAR;
    1369         }
    1370 
    1371         out->attid                      = attr->attributeID_id;
    1372         out->value_ctr.num_values       = in->num_values;
    1373         out->value_ctr.values           = talloc_array(mem_ctx,
    1374                                                        struct drsuapi_DsAttributeValue,
    1375                                                        in->num_values);
    1376         W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
    1377 
    1378         blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
    1379         W_ERROR_HAVE_NO_MEMORY(blobs);
    1380 
    1381         for (i=0; i < in->num_values; i++) {
    13822284                uint8_t *data;
    13832285                size_t ret;
     
    13852287                out->value_ctr.values[i].blob   = &blobs[i];
    13862288
    1387                 if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
    1388                                             in->values[i].data,
    1389                                             in->values[i].length,
    1390                                             (void **)&data, &ret, false)) {
     2289                if (!convert_string_talloc(blobs, CH_UNIX, CH_UTF16,
     2290                                           in->values[i].data,
     2291                                           in->values[i].length,
     2292                                           (void **)&data, &ret, false)) {
    13912293                        return WERR_FOOBAR;
    13922294                }
     
    14042306
    14052307        return WERR_OK;
     2308}
     2309
     2310static WERROR dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb(const struct dsdb_syntax_ctx *ctx,
     2311                                                            const struct dsdb_attribute *attr,
     2312                                                            const struct ldb_message_element *in)
     2313{
     2314        return dsdb_syntax_UNICODE_validate_ldb(ctx,
     2315                                                attr,
     2316                                                in);
    14062317}
    14072318
     
    14162327                .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
    14172328                .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
     2329                .validate_ldb           = dsdb_syntax_BOOL_validate_ldb,
    14182330                .equality               = "booleanMatch",
    1419                 .comment                = "Boolean" 
     2331                .comment                = "Boolean"
    14202332        },{
    14212333                .name                   = "Integer",
     
    14252337                .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
    14262338                .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
     2339                .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
    14272340                .equality               = "integerMatch",
    14282341                .comment                = "Integer",
     
    14352348                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
    14362349                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2350                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
    14372351                .equality               = "octetStringMatch",
    14382352                .comment                = "Octet String",
     
    14442358                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
    14452359                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2360                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
    14462361                .equality               = "octetStringMatch",
    14472362                .comment                = "Octet String - Security Identifier (SID)",
     
    14542369                .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
    14552370                .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
     2371                .validate_ldb           = dsdb_syntax_OID_validate_ldb,
    14562372                .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
    14572373                .comment                = "OID String",
     
    14642380                .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
    14652381                .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
     2382                .validate_ldb           = dsdb_syntax_INT32_validate_ldb,
    14662383                .ldb_syntax             = LDB_SYNTAX_SAMBA_INT32
    14672384        },{
     
    14732390                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
    14742391                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2392                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
    14752393                .equality               = "numericStringMatch",
    14762394                .substring              = "numericStringSubstringsMatch",
     
    14842402                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
    14852403                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2404                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
    14862405                .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
    14872406        },{
     
    14922411                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
    14932412                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2413                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
    14942414                .equality               = "caseIgnoreMatch",
    14952415                .substring              = "caseIgnoreSubstringsMatch",
     
    15032423                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
    15042424                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2425                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
    15052426                .equality               = "caseExactIA5Match",
    15062427                .comment                = "Printable String",
     
    15132434                .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
    15142435                .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
     2436                .validate_ldb           = dsdb_syntax_NTTIME_UTC_validate_ldb,
    15152437                .equality               = "generalizedTimeMatch",
    15162438                .comment                = "UTC Time",
     
    15222444                .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
    15232445                .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
     2446                .validate_ldb           = dsdb_syntax_NTTIME_validate_ldb,
    15242447                .equality               = "generalizedTimeMatch",
    15252448                .comment                = "Generalized Time",
     
    15312454                .oMSyntax               = 27,
    15322455                .attributeSyntax_oid    = "2.5.5.3",
    1533                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
    1534                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
     2456                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
     2457                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2458                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
     2459                .equality               = "caseExactMatch",
     2460                .substring              = "caseExactSubstringsMatch",
     2461                /* TODO (kim): according to LDAP rfc we should be using same comparison
     2462                 * as Directory String (LDB_SYNTAX_DIRECTORY_STRING), but case sensitive.
     2463                 * But according to ms docs binary compare should do the job:
     2464                 * http://msdn.microsoft.com/en-us/library/cc223200(v=PROT.10).aspx */
     2465                .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
    15352466        },{
    15362467                .name                   = "String(Unicode)",
     
    15402471                .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
    15412472                .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
     2473                .validate_ldb           = dsdb_syntax_UNICODE_validate_ldb,
    15422474                .equality               = "caseIgnoreMatch",
    15432475                .substring              = "caseIgnoreSubstringsMatch",
     
    15502482                .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
    15512483                .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
     2484                .validate_ldb           = dsdb_syntax_INT64_validate_ldb,
    15522485                .equality               = "integerMatch",
    15532486                .comment                = "Large Integer",
     
    15602493                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
    15612494                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2495                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
    15622496        },{
    15632497                .name                   = "Object(DS-DN)",
     
    15682502                .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
    15692503                .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
     2504                .validate_ldb           = dsdb_syntax_DN_validate_ldb,
    15702505                .equality               = "distinguishedNameMatch",
    15712506                .comment                = "Object(DS-DN) == a DN",
    15722507        },{
    15732508                .name                   = "Object(DN-Binary)",
    1574                 .ldap_oid               = "1.2.840.113556.1.4.903",
     2509                .ldap_oid               = DSDB_SYNTAX_BINARY_DN,
    15752510                .oMSyntax               = 127,
    15762511                .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
     
    15782513                .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
    15792514                .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
     2515                .validate_ldb           = dsdb_syntax_DN_BINARY_validate_ldb,
    15802516                .equality               = "octetStringMatch",
    15812517                .comment                = "OctetString: Binary+DN",
    1582                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
    15832518        },{
    1584         /* not used in w2k3 schema */
     2519        /* not used in w2k3 schema, but used in Exchange schema*/
    15852520                .name                   = "Object(OR-Name)",
    1586                 .ldap_oid               = "1.2.840.113556.1.4.1221",
     2521                .ldap_oid               = DSDB_SYNTAX_OR_NAME,
    15872522                .oMSyntax               = 127,
    15882523                .oMObjectClass          = OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
    15892524                .attributeSyntax_oid    = "2.5.5.7",
    1590                 .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
    1591                 .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
     2525                .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
     2526                .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
     2527                .validate_ldb           = dsdb_syntax_DN_BINARY_validate_ldb,
     2528                .equality               = "caseIgnoreMatch",
     2529                .ldb_syntax             = LDB_SYNTAX_DN,
    15922530        },{
    1593         /* 
     2531        /*
    15942532         * TODO: verify if DATA_BLOB is correct here...!
    15952533         *
    15962534         *       repsFrom and repsTo are the only attributes using
    1597          *       this attribute syntax, but they're not replicated... 
     2535         *       this attribute syntax, but they're not replicated...
    15982536         */
    15992537                .name                   = "Object(Replica-Link)",
     
    16042542                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
    16052543                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
     2544                .validate_ldb           = dsdb_syntax_DATA_BLOB_validate_ldb,
    16062545        },{
    16072546                .name                   = "Object(Presentation-Address)",
     
    16122551                .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
    16132552                .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
     2553                .validate_ldb           = dsdb_syntax_PRESENTATION_ADDRESS_validate_ldb,
    16142554                .comment                = "Presentation Address",
    16152555                .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
     
    16232563                .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
    16242564                .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
     2565                .validate_ldb           = dsdb_syntax_FOOBAR_validate_ldb,
    16252566                .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
    16262567        },{
    16272568        /* not used in w2k3 schema */
    16282569                .name                   = "Object(DN-String)",
    1629                 .ldap_oid               = "1.2.840.113556.1.4.904",
     2570                .ldap_oid               = DSDB_SYNTAX_STRING_DN,
    16302571                .oMSyntax               = 127,
    16312572                .oMObjectClass          = OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
    16322573                .attributeSyntax_oid    = "2.5.5.14",
    1633                 .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
    1634                 .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
     2574                .drsuapi_to_ldb         = dsdb_syntax_DN_STRING_drsuapi_to_ldb,
     2575                .ldb_to_drsuapi         = dsdb_syntax_DN_STRING_ldb_to_drsuapi,
     2576                .validate_ldb           = dsdb_syntax_DN_STRING_validate_ldb,
    16352577                .equality               = "octetStringMatch",
    16362578                .comment                = "OctetString: String+DN",
    1637                 .ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
    16382579        }
    16392580};
    16402581
    1641 const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
    1642 {
    1643         int i;
     2582const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
     2583{
     2584        unsigned int i;
    16442585        for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
    16452586                if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
     
    16502591}
    16512592
    1652 const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
    1653 {
    1654         int i;
     2593const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
     2594{
     2595        unsigned int i;
    16552596        for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
    16562597                if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
     
    16612602}
    16622603
    1663 const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
    1664 {
    1665         int i;
     2604const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
     2605{
     2606        unsigned int i;
    16662607        for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
    16672608                if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
     
    16712612        return NULL;
    16722613}
     2614
    16732615const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
    16742616{
    1675         uint32_t i;
     2617        unsigned int i;
    16762618
    16772619        for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
     
    16962638}
    16972639
    1698 WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb, 
     2640WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb,
    16992641                                     const struct dsdb_schema *schema,
     2642                                     const struct dsdb_schema_prefixmap *pfm_remote,
    17002643                                     const struct drsuapi_DsReplicaAttribute *in,
    17012644                                     TALLOC_CTX *mem_ctx,
     
    17032646{
    17042647        const struct dsdb_attribute *sa;
    1705 
    1706         sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
     2648        struct dsdb_syntax_ctx syntax_ctx;
     2649        uint32_t attid_local;
     2650
     2651        /* use default syntax conversion context */
     2652        dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
     2653        syntax_ctx.pfm_remote = pfm_remote;
     2654
     2655        switch (dsdb_pfm_get_attid_type(in->attid)) {
     2656        case DSDB_ATTID_TYPE_PFM:
     2657                /* map remote ATTID to local ATTID */
     2658                if (!dsdb_syntax_attid_from_remote_attid(&syntax_ctx, mem_ctx, in->attid, &attid_local)) {
     2659                        DEBUG(0,(__location__ ": Can't find local ATTID for 0x%08X\n",
     2660                                 in->attid));
     2661                        return WERR_FOOBAR;
     2662                }
     2663                break;
     2664        case DSDB_ATTID_TYPE_INTID:
     2665                /* use IntId value directly */
     2666                attid_local = in->attid;
     2667                break;
     2668        default:
     2669                /* we should never get here */
     2670                DEBUG(0,(__location__ ": Invalid ATTID type passed for conversion - 0x%08X\n",
     2671                         in->attid));
     2672                return WERR_INVALID_PARAMETER;
     2673        }
     2674
     2675        sa = dsdb_attribute_by_attributeID_id(schema, attid_local);
    17072676        if (!sa) {
    1708                 return WERR_FOOBAR;
    1709         }
    1710 
    1711         return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
    1712 }
    1713 
    1714 WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb,
     2677                DEBUG(1,(__location__ ": Unknown attributeID_id 0x%08X\n", in->attid));
     2678                return WERR_FOOBAR;
     2679        }
     2680
     2681        return sa->syntax->drsuapi_to_ldb(&syntax_ctx, sa, in, mem_ctx, out);
     2682}
     2683
     2684WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb,
    17152685                                     const struct dsdb_schema *schema,
    17162686                                     const struct ldb_message_element *in,
     
    17192689{
    17202690        const struct dsdb_attribute *sa;
     2691        struct dsdb_syntax_ctx syntax_ctx;
    17212692
    17222693        sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
     
    17252696        }
    17262697
    1727         return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
    1728 }
     2698        /* use default syntax conversion context */
     2699        dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
     2700
     2701        return sa->syntax->ldb_to_drsuapi(&syntax_ctx, sa, in, mem_ctx, out);
     2702}
     2703
Note: See TracChangeset for help on using the changeset viewer.