The branch, master has been updated via 431d75f... s4:NBT-WINS: test large scopes via 70779a4... s4:NBT-WINS: pass the expected rcode of the name registration to the test code via c1d8dc0... s4:NBT-WINSREPLICATION: test replication with names including scopes via 331505f... s4:NBT-WINSREPLICATION: fix compiler warnings via 07b06e5... s4:NBT-WINSREPLICATION: use an array of nbt_names to loop over different names via ea7ec4f... s4:winsserver: reject name registrations with a scope length > 237 via 7a02a2b... s4:wrepl_server: truncate the scope of a netbios name to 237 bytes as Windows 2008 does via e37dc56... libcli/nbt: fix ndr_push_nbt_string() string labels with a length of 63 (0x3F) are allowed from 93142e4... s4/ldif: Handle Schema:prefixMap blobs in W2K3 and W2K8
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 431d75fc9c7f942dcbd31f80380dda59887ac229 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Feb 1 15:32:37 2010 +0100 s4:NBT-WINS: test large scopes metze commit 70779a46a7b7f6e5c00eba048dbf653d86bc07d4 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Feb 1 14:55:14 2010 +0100 s4:NBT-WINS: pass the expected rcode of the name registration to the test code metze commit c1d8dc01fc6f0fa3a22a405419917d880b832761 Author: Stefan Metzmacher <me...@samba.org> Date: Sat Jan 30 10:50:33 2010 +0100 s4:NBT-WINSREPLICATION: test replication with names including scopes metze commit 331505f09d61cdc5c920293fc36ac1853235177b Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jan 29 16:42:24 2010 +0100 s4:NBT-WINSREPLICATION: fix compiler warnings metze commit 07b06e51bbf95168899081ba2aa92a4e6a5bac12 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jan 29 16:33:58 2010 +0100 s4:NBT-WINSREPLICATION: use an array of nbt_names to loop over different names metze commit ea7ec4fb30a261cedb882c9325815679e5e20d57 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Feb 1 14:39:13 2010 +0100 s4:winsserver: reject name registrations with a scope length > 237 This matches Windows 2008 behavior. Name releases are just ignored. metze commit 7a02a2ba80c2997947a2b2c48c33f8c7647f7471 Author: Stefan Metzmacher <me...@samba.org> Date: Sun Jan 31 18:59:41 2010 +0100 s4:wrepl_server: truncate the scope of a netbios name to 237 bytes as Windows 2008 does metze commit e37dc56e971f44c00791529a39144d1a972e3ca2 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Feb 1 15:18:15 2010 +0100 libcli/nbt: fix ndr_push_nbt_string() string labels with a length of 63 (0x3F) are allowed metze ----------------------------------------------------------------------- Summary of changes: libcli/nbt/nbtname.c | 4 +- source4/nbt_server/wins/winsserver.c | 9 +++ source4/torture/nbt/wins.c | 94 ++++++++++++++++++++++----- source4/torture/nbt/winsreplication.c | 93 ++++++++++++++++++++++------ source4/wrepl_server/wrepl_apply_records.c | 14 ++++ 5 files changed, 175 insertions(+), 39 deletions(-) Changeset truncated at 500 lines: diff --git a/libcli/nbt/nbtname.c b/libcli/nbt/nbtname.c index 792b340..136379a 100644 --- a/libcli/nbt/nbtname.c +++ b/libcli/nbt/nbtname.c @@ -173,9 +173,9 @@ _PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_fla complen = strcspn(s, "."); /* we need to make sure the length fits into 6 bytes */ - if (complen >= 0x3F) { + if (complen > 0x3F) { return ndr_push_error(ndr, NDR_ERR_STRING, - "component length %u[%08X] > 0x00003F", + "component length %u[%08X] > 0x0000003F", (unsigned)complen, (unsigned)complen); } diff --git a/source4/nbt_server/wins/winsserver.c b/source4/nbt_server/wins/winsserver.c index 4b8b8cc..ca8daed 100644 --- a/source4/nbt_server/wins/winsserver.c +++ b/source4/nbt_server/wins/winsserver.c @@ -496,6 +496,11 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock, goto done; } + if (name->scope && strlen(name->scope) > 237) { + rcode = NBT_RCODE_SVR; + goto done; + } + duplicate_packet = wins_check_wack_queue(iface, packet, src); if (duplicate_packet) { /* just ignore the packet */ @@ -874,6 +879,10 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock, goto done; } + if (name->scope && strlen(name->scope) > 237) { + goto done; + } + status = winsdb_lookup(winssrv->wins_db, name, packet, &rec); if (!NT_STATUS_IS_OK(status)) { goto done; diff --git a/source4/torture/nbt/wins.c b/source4/torture/nbt/wins.c index d69c518..b372de8 100644 --- a/source4/torture/nbt/wins.c +++ b/source4/torture/nbt/wins.c @@ -49,7 +49,8 @@ */ static bool nbt_test_wins_name(struct torture_context *tctx, const char *address, struct nbt_name *name, uint16_t nb_flags, - bool try_low_port) + bool try_low_port, + uint8_t register_rcode) { struct nbt_name_register_wins io; struct nbt_name_register name_register; @@ -200,7 +201,11 @@ static bool nbt_test_wins_name(struct torture_context *tctx, const char *address torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name register", address)); CHECK_STRING(tctx, io.out.wins_server, address); - CHECK_VALUE(tctx, io.out.rcode, 0); + CHECK_VALUE(tctx, io.out.rcode, register_rcode); + + if (register_rcode != NBT_RCODE_OK) { + return true; + } if (name->type != NBT_NAME_MASTER && name->type != NBT_NAME_LOGON && @@ -400,6 +405,35 @@ static bool nbt_test_wins_name(struct torture_context *tctx, const char *address } +static char *test_nbt_wins_scope_string(TALLOC_CTX *mem_ctx, uint8_t count) +{ + char *res; + uint8_t i; + + res = talloc_array(mem_ctx, char, count+1); + if (res == NULL) { + return NULL; + } + + for (i=0; i < count; i++) { + switch (i) { + case 63: + case 63 + 1 + 63: + case 63 + 1 + 63 + 1 + 63: + res[i] = '.'; + break; + default: + res[i] = '0' + (i%10); + break; + } + } + + res[count] = '\0'; + + talloc_set_name_const(res, res); + + return res; +} /* test operations against a WINS server @@ -418,54 +452,78 @@ static bool nbt_test_wins(struct torture_context *tctx) name.type = NBT_NAME_CLIENT; name.scope = NULL; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, true); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, true, NBT_RCODE_OK); name.type = NBT_NAME_MASTER; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_OK); - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H | NBT_NM_GROUP, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H | NBT_NM_GROUP, false, NBT_RCODE_OK); name.type = NBT_NAME_SERVER; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, true); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, true, NBT_RCODE_OK); name.type = NBT_NAME_LOGON; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H | NBT_NM_GROUP, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H | NBT_NM_GROUP, false, NBT_RCODE_OK); name.type = NBT_NAME_BROWSER; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H | NBT_NM_GROUP, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H | NBT_NM_GROUP, false, NBT_RCODE_OK); name.type = NBT_NAME_PDC; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, true); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, true, NBT_RCODE_OK); name.type = 0xBF; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, true); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, true, NBT_RCODE_OK); name.type = 0xBE; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_OK); name.scope = "example"; name.type = 0x72; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, true); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, true, NBT_RCODE_OK); name.scope = "example"; name.type = 0x71; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H | NBT_NM_GROUP, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H | NBT_NM_GROUP, false, NBT_RCODE_OK); name.scope = "foo.example.com"; name.type = 0x72; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_OK); name.name = talloc_asprintf(tctx, "_T\01-%5u.foo", r); - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_OK); name.name = ""; - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_OK); name.name = talloc_asprintf(tctx, "."); - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_OK); name.name = talloc_asprintf(tctx, "%5u-\377\200\300FOO", r); - ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H, false); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_OK); + + name.scope = test_nbt_wins_scope_string(tctx, 237); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_OK); + + name.scope = test_nbt_wins_scope_string(tctx, 238); + ret &= nbt_test_wins_name(tctx, address, &name, + NBT_NODE_H, false, NBT_RCODE_SVR); return ret; } diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c index 1ad0543..f363c9e 100644 --- a/source4/torture/nbt/winsreplication.c +++ b/source4/torture/nbt/winsreplication.c @@ -799,9 +799,16 @@ static bool test_wrepl_is_applied(struct torture_context *tctx, names[0].state, names[0].node, names[0].is_static); + char *expected_scope = NULL; CHECK_VALUE(tctx, names[0].name.type, name->name->type); CHECK_VALUE_STRING(tctx, names[0].name.name, name->name->name); - CHECK_VALUE_STRING(tctx, names[0].name.scope, name->name->scope); + + if (names[0].name.scope) { + expected_scope = talloc_strndup(tctx, + name->name->scope, + 237); + } + CHECK_VALUE_STRING(tctx, names[0].name.scope, expected_scope); CHECK_VALUE(tctx, flags, name->flags); CHECK_VALUE_UINT64(tctx, names[0].version_id, name->id); @@ -1004,18 +1011,63 @@ static bool test_wrepl_sgroup_merged(struct torture_context *tctx, return true; } +static char *test_nbt_winsrepl_scope_string(TALLOC_CTX *mem_ctx, uint8_t count) +{ + char *res; + uint8_t i; + + res = talloc_array(mem_ctx, char, count+1); + if (res == NULL) { + return NULL; + } + + for (i=0; i < count; i++) { + res[i] = '0' + (i%10); + } + + res[count] = '\0'; + + talloc_set_name_const(res, res); + + return res; +} + static bool test_conflict_same_owner(struct torture_context *tctx, struct test_wrepl_conflict_conn *ctx) { static bool ret = true; - struct nbt_name name; struct wrepl_wins_name wins_name1; struct wrepl_wins_name wins_name2; struct wrepl_wins_name *wins_name_tmp; struct wrepl_wins_name *wins_name_last; struct wrepl_wins_name *wins_name_cur; uint32_t i,j; - uint8_t types[] = { 0x00, 0x1C }; + struct nbt_name names[] = { + _NBT_NAME("_SAME_OWNER_A", 0x00, NULL), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 1)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 2)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 3)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 4)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 5)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 6)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 7)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 8)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 9)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 237)), + _NBT_NAME("_SAME_OWNER_A", 0x00, + test_nbt_winsrepl_scope_string(tctx, 238)), + _NBT_NAME("_SAME_OWNER_A", 0x1C, NULL), + }; struct { enum wrepl_name_type type; enum wrepl_name_state state; @@ -1112,18 +1164,13 @@ static bool test_conflict_same_owner(struct torture_context *tctx, } }; - name.name = "_SAME_OWNER_A"; - name.type = 0; - name.scope = NULL; - wins_name_tmp = NULL; wins_name_last = &wins_name2; wins_name_cur = &wins_name1; - for (j=0; ret && j < ARRAY_SIZE(types); j++) { - name.type = types[j]; + for (j=0; ret && j < ARRAY_SIZE(names); j++) { torture_comment(tctx, "Test Replica Conflicts with same owner[%s] for %s\n", - nbt_name_string(ctx, &name), ctx->a.address); + nbt_name_string(ctx, &names[j]), ctx->a.address); for(i=0; ret && i < ARRAY_SIZE(records); i++) { wins_name_tmp = wins_name_last; @@ -1142,7 +1189,7 @@ static bool test_conflict_same_owner(struct torture_context *tctx, "REPLACE"); } - wins_name_cur->name = &name; + wins_name_cur->name = &names[j]; wins_name_cur->flags = WREPL_NAME_FLAGS(records[i].type, records[i].state, records[i].node, @@ -1150,7 +1197,8 @@ static bool test_conflict_same_owner(struct torture_context *tctx, wins_name_cur->id = ++ctx->a.max_version; if (wins_name_cur->flags & 2) { wins_name_cur->addresses.addresses.num_ips = records[i].num_ips; - wins_name_cur->addresses.addresses.ips = discard_const(records[i].ips); + wins_name_cur->addresses.addresses.ips = discard_const_p(struct wrepl_ip, + records[i].ips); } else { wins_name_cur->addresses.ip = records[i].ips[0].ip; } @@ -4833,7 +4881,8 @@ static bool test_conflict_different_owner(struct torture_context *tctx, wins_name_r1->id = ++records[i].r1.owner->max_version; if (wins_name_r1->flags & 2) { wins_name_r1->addresses.addresses.num_ips = records[i].r1.num_ips; - wins_name_r1->addresses.addresses.ips = discard_const(records[i].r1.ips); + wins_name_r1->addresses.addresses.ips = discard_const_p(struct wrepl_ip, + records[i].r1.ips); } else { wins_name_r1->addresses.ip = records[i].r1.ips[0].ip; } @@ -4855,7 +4904,8 @@ static bool test_conflict_different_owner(struct torture_context *tctx, wins_name_r2->id = ++records[i].r2.owner->max_version; if (wins_name_r2->flags & 2) { wins_name_r2->addresses.addresses.num_ips = records[i].r2.num_ips; - wins_name_r2->addresses.addresses.ips = discard_const(records[i].r2.ips); + wins_name_r2->addresses.addresses.ips = discard_const_p(struct wrepl_ip, + records[i].r2.ips); } else { wins_name_r2->addresses.ip = records[i].r2.ips[0].ip; } @@ -4932,7 +4982,8 @@ static bool test_conflict_different_owner(struct torture_context *tctx, WREPL_NODE_B, false); wins_name_r2->id = ++records[i].r2.owner->max_version; wins_name_r2->addresses.addresses.num_ips = ARRAY_SIZE(addresses_B_1); - wins_name_r2->addresses.addresses.ips = discard_const(addresses_B_1); + wins_name_r2->addresses.addresses.ips = discard_const_p(struct wrepl_ip, + addresses_B_1); wins_name_r2->unknown = "255.255.255.255"; ret &= test_wrepl_update_one(tctx, ctx, records[i].r2.owner, wins_name_r2); ret &= test_wrepl_is_applied(tctx, ctx, records[i].r2.owner, wins_name_r2, true); @@ -4944,7 +4995,8 @@ static bool test_conflict_different_owner(struct torture_context *tctx, WREPL_NODE_B, false); wins_name_r2->id = ++records[i].r2.owner->max_version; wins_name_r2->addresses.addresses.num_ips = ARRAY_SIZE(addresses_B_1); - wins_name_r2->addresses.addresses.ips = discard_const(addresses_B_1); + wins_name_r2->addresses.addresses.ips = discard_const_p(struct wrepl_ip, + addresses_B_1); wins_name_r2->unknown = "255.255.255.255"; ret &= test_wrepl_update_one(tctx, ctx, records[i].r2.owner, wins_name_r2); ret &= test_wrepl_is_applied(tctx, ctx, records[i].r2.owner, wins_name_r2, true); @@ -6592,7 +6644,8 @@ static bool test_conflict_owned_released_vs_replica(struct torture_context *tctx wins_name->id = ++ctx->b.max_version; if (wins_name->flags & 2) { wins_name->addresses.addresses.num_ips = records[i].replica.num_ips; - wins_name->addresses.addresses.ips = discard_const(records[i].replica.ips); + wins_name->addresses.addresses.ips = discard_const_p(struct wrepl_ip, + records[i].replica.ips); } else { wins_name->addresses.ip = records[i].replica.ips[0].ip; } @@ -9289,7 +9342,8 @@ static bool test_conflict_owned_active_vs_replica(struct torture_context *tctx, wins_name->id = ++ctx->b.max_version; if (wins_name->flags & 2) { wins_name->addresses.addresses.num_ips = records[i].replica.num_ips; - wins_name->addresses.addresses.ips = discard_const(records[i].replica.ips); + wins_name->addresses.addresses.ips = discard_const_p(struct wrepl_ip, + records[i].replica.ips); } else { wins_name->addresses.ip = records[i].replica.ips[0].ip; } @@ -9404,7 +9458,8 @@ static bool test_conflict_owned_active_vs_replica(struct torture_context *tctx, WREPL_NODE_B, false); wins_name->id = ++ctx->b.max_version; wins_name->addresses.addresses.num_ips = ARRAY_SIZE(addresses_B_1); - wins_name->addresses.addresses.ips = discard_const(addresses_B_1); + wins_name->addresses.addresses.ips = discard_const_p(struct wrepl_ip, + addresses_B_1); wins_name->unknown = "255.255.255.255"; ret &= test_wrepl_update_one(tctx, ctx, &ctx->b, wins_name); ret &= test_wrepl_is_applied(tctx, ctx, &ctx->b, wins_name, true); diff --git a/source4/wrepl_server/wrepl_apply_records.c b/source4/wrepl_server/wrepl_apply_records.c index e6ff9a0..878f689 100644 --- a/source4/wrepl_server/wrepl_apply_records.c +++ b/source4/wrepl_server/wrepl_apply_records.c @@ -1358,6 +1358,20 @@ static NTSTATUS wreplsrv_apply_one_record(struct wreplsrv_partner *partner, bool replica_vs_replica = false; bool local_vs_replica = false; + if (replica->name.scope) { + TALLOC_CTX *parent; + const char *scope; + + /* + * Windows 2008 truncates the scope to 237 bytes, + * so we do... + */ + parent = talloc_parent(replica->name.scope); + scope = talloc_strndup(parent, replica->name.scope, 237); + NT_STATUS_HAVE_NO_MEMORY(scope); + replica->name.scope = scope; + } + status = winsdb_lookup(partner->service->wins_db, &replica->name, mem_ctx, &rec); if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) { -- Samba Shared Repository