From 4c0399915cde591cb06f99b50acd5e5bf48bc6cb Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 11 Apr 2002 23:43:40 +0000 Subject: Much better support for both non-algorithic RIDs (where the RID is stored in the passdb) and RIDs not in the passdb, due to being NIS users etc. The main fix here is to add become_root()/unbecome_root() at critical places. This (finally) fixes the bug where you could not see local users's names in a file's security properties as non-root. Tested. The similar bug in uid_to_sid is also fixed, but is not (yet) Tested. Andrew Bartlett (This used to be commit 79327a305e20d78ab5ca21d01c39b5f49dc0d632) --- source3/passdb/passdb.c | 265 +++++++++++++++++++-------------------- source3/rpc_server/srv_samr_nt.c | 15 --- source3/smbd/uid.c | 20 ++- 3 files changed, 145 insertions(+), 155 deletions(-) diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 7eecbfd2cd..17aefe1159 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -514,121 +514,116 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use uint32 rid; BOOL is_user; SAM_ACCOUNT *sam_account = NULL; - BOOL found = False; + uid_t uid; + struct passwd *pass; + GROUP_MAP map; + sid_peek_rid(sid, &rid); - is_user = pdb_rid_is_user(rid); *psid_name_use = SID_NAME_UNKNOWN; - - DEBUG(5,("local_lookup_sid: looking up %s RID %u.\n", is_user ? "user" : - "group", (unsigned int)rid)); - - if(is_user) { - if(rid == DOMAIN_USER_RID_ADMIN) { - char **admin_list = lp_admin_users(-1); - *psid_name_use = SID_NAME_USER; - if (admin_list) { - char *p = *admin_list; - if(!next_token(&p, name, NULL, sizeof(fstring))) - fstrcpy(name, "Administrator"); - } else { - fstrcpy(name, "Administrator"); - } - } else if (rid == DOMAIN_USER_RID_GUEST) { - char *p = lp_guestaccount(); - *psid_name_use = SID_NAME_USER; + + DEBUG(5,("local_lookup_sid: looking up RID %u.\n", (unsigned int)rid)); + + if (rid == DOMAIN_USER_RID_ADMIN) { + char **admin_list = lp_admin_users(-1); + *psid_name_use = SID_NAME_USER; + if (admin_list) { + char *p = *admin_list; if(!next_token(&p, name, NULL, sizeof(fstring))) - fstrcpy(name, "Guest"); + fstrcpy(name, "Administrator"); } else { - uid_t uid; - struct passwd *pass; - - /* - * Don't try to convert the rid to a name if - * running in appliance mode - */ - if (lp_hide_local_users()) - return False; + fstrcpy(name, "Administrator"); + } + return True; - if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { - return False; - } - - if (pdb_getsampwrid(sam_account, rid)) { - fstrcpy(name, pdb_get_username(sam_account)); - *psid_name_use = SID_NAME_USER; - found = True; - } - - pdb_free_sam(&sam_account); + } else if (rid == DOMAIN_USER_RID_GUEST) { + char *p = lp_guestaccount(); + *psid_name_use = SID_NAME_USER; + if(!next_token(&p, name, NULL, sizeof(fstring))) + fstrcpy(name, "Guest"); + return True; + + } + + /* + * Don't try to convert the rid to a name if + * running in appliance mode + */ + + if (lp_hide_local_users()) + return False; + + if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { + return False; + } + + if (pdb_getsampwrid(sam_account, rid)) { + fstrcpy(name, pdb_get_username(sam_account)); + *psid_name_use = SID_NAME_USER; + + pdb_free_sam(&sam_account); - if (found) { - return True; - } + return True; + } + + pdb_free_sam(&sam_account); + + if (get_group_map_from_sid(*sid, &map, MAPPING_WITHOUT_PRIV)) { + if (map.gid!=-1) { + DEBUG(5,("local_lookup_sid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid)); + fstrcpy(name, map.nt_name); + *psid_name_use = map.sid_name_use; + return True; + } + } + + is_user = pdb_rid_is_user(rid); + + DEBUG(5, ("assuming RID %u is a %s\n", (unsigned)rid, is_user ? "user" : "group")); + + if (pdb_rid_is_user(rid)) { + uid = fallback_pdb_user_rid_to_uid(rid); + pass = getpwuid_alloc(uid); - uid = fallback_pdb_user_rid_to_uid(rid); - pass = getpwuid_alloc(uid); + *psid_name_use = SID_NAME_USER; - *psid_name_use = SID_NAME_USER; + DEBUG(5,("local_lookup_sid: looking up uid %u %s\n", (unsigned int)uid, + pass ? "succeeded" : "failed" )); - DEBUG(5,("local_lookup_sid: looking up uid %u %s\n", (unsigned int)uid, - pass ? "succeeded" : "failed" )); + if(!pass) { + slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); + return True; + } - if(!pass) { - slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); - return True; - } + fstrcpy(name, pass->pw_name); - fstrcpy(name, pass->pw_name); + DEBUG(5,("local_lookup_sid: found user %s for rid %u\n", name, + (unsigned int)rid )); - DEBUG(5,("local_lookup_sid: found user %s for rid %u\n", name, - (unsigned int)rid )); + passwd_free(&pass); - passwd_free(&pass); - } - } else { gid_t gid; struct group *gr; - GROUP_MAP map; - - /* - * Don't try to convert the rid to a name if running - * in appliance mode - */ - - if (lp_hide_local_users()) - return False; - - /* check if it's a mapped group */ - if (get_group_map_from_sid(*sid, &map, MAPPING_WITHOUT_PRIV)) { - if (map.gid!=-1) { - DEBUG(5,("local_lookup_sid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid)); - fstrcpy(name, map.nt_name); - *psid_name_use = map.sid_name_use; - return True; - } - } - + gid = pdb_group_rid_to_gid(rid); gr = getgrgid(gid); - + *psid_name_use = SID_NAME_ALIAS; - + DEBUG(5,("local_lookup_sid: looking up gid %u %s\n", (unsigned int)gid, - gr ? "succeeded" : "failed" )); - + gr ? "succeeded" : "failed" )); + if(!gr) { slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid); return False; } - + fstrcpy( name, gr->gr_name); - + DEBUG(5,("local_lookup_sid: found group %s for rid %u\n", name, - (unsigned int)rid )); + (unsigned int)rid )); } - return True; } @@ -643,7 +638,6 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi DOM_SID local_sid; fstring user; SAM_ACCOUNT *sam_account = NULL; - BOOL found = False; *psid_name_use = SID_NAME_UNKNOWN; @@ -684,25 +678,23 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi *psid_name_use = SID_NAME_USER; sid_copy( psid, &local_sid); - found = True; + pdb_free_sam(&sam_account); + return True; } pdb_free_sam(&sam_account); - if (!found && (pass = Get_Pwnam(user))) { + if ((pass = Get_Pwnam(user))) { sid_append_rid( &local_sid, fallback_pdb_uid_to_user_rid(pass->pw_uid)); *psid_name_use = SID_NAME_USER; - pdb_free_sam(&sam_account); - } else if (!found) { + } else { /* * Maybe it was a group ? */ struct group *grp; GROUP_MAP map; - pdb_free_sam(&sam_account); - /* check if it's a mapped group */ if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) { if (map.gid!=-1) { @@ -754,27 +746,36 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) extern DOM_SID global_sam_sid; struct passwd *pass; SAM_ACCOUNT *sam_user = NULL; + fstring str; /* sid string buffer */ sid_copy(psid, &global_sam_sid); - if(!(pass = getpwuid_alloc(uid))) - return NULL; + if((pass = getpwuid_alloc(uid))) { - if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) { - passwd_free(&pass); - return NULL; - } - - if (!pdb_getsampwnam(sam_user, pass->pw_name)) { - pdb_free_sam(&sam_user); - return NULL; - } + if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) { + passwd_free(&pass); + return NULL; + } + + if (pdb_getsampwnam(sam_user, pass->pw_name)) { + sid_append_rid(psid, pdb_get_user_rid(sam_user)); + } else { + sid_append_rid(psid, fallback_pdb_uid_to_user_rid(uid)); + } - passwd_free(&pass); + DEBUG(10,("local_uid_to_sid: uid %u -> SID (%s) (%s).\n", + (unsigned)uid, sid_to_string( str, psid), + pass->pw_name )); - sid_append_rid(psid, pdb_get_user_rid(sam_user)); + passwd_free(&pass); + pdb_free_sam(&sam_user); + + } else { + sid_append_rid(psid, fallback_pdb_uid_to_user_rid(uid)); - pdb_free_sam(&sam_user); + DEBUG(10,("local_uid_to_sid: uid %u -> SID (%s) (unknown user).\n", + (unsigned)uid, sid_to_string( str, psid))); + } return psid; } @@ -790,7 +791,6 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) DOM_SID dom_sid; uint32 rid; fstring str; - struct passwd *pass; SAM_ACCOUNT *sam_user = NULL; *name_type = SID_NAME_UNKNOWN; @@ -798,9 +798,6 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) sid_copy(&dom_sid, psid); sid_split_rid(&dom_sid, &rid); - if (!pdb_rid_is_user(rid)) - return False; - /* * We can only convert to a uid if this is our local * Domain SID (ie. we are the controling authority). @@ -811,28 +808,26 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) return False; - if (!pdb_getsampwrid(sam_user, rid)) { - pdb_free_sam(&sam_user); - return False; + if (pdb_getsampwrid(sam_user, rid)) { + *puid = pdb_get_uid(sam_user); + if (*puid == -1) { + pdb_free_sam(&sam_user); + return False; + } + DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid), + (unsigned int)*puid, pdb_get_username(sam_user))); + } else { + if (pdb_rid_is_user(rid)) { + *puid = fallback_pdb_user_rid_to_uid(rid); + DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (non-passdb user).\n", sid_to_string( str, psid), + (unsigned int)*puid)); + } else { + pdb_free_sam(&sam_user); + return False; + } } - - *puid = pdb_get_uid(sam_user); - if (*puid == -1) - return False; - pdb_free_sam(&sam_user); - /* - * Ensure this uid really does exist. - */ - if(!(pass = getpwuid_alloc(*puid))) - return False; - - DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid), - (unsigned int)*puid, pass->pw_name )); - - passwd_free(&pass); - *name_type = SID_NAME_USER; return True; @@ -887,9 +882,6 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) if (!sid_equal(&global_sam_sid, &dom_sid)) return False; - if (pdb_rid_is_user(rid)) - return False; - if (get_group_map_from_sid(*psid, &map, MAPPING_WITHOUT_PRIV)) { /* the SID is in the mapping table but not mapped */ @@ -897,9 +889,12 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) return False; sid_peek_rid(&map.sid, &rid); - *pgid = rid; + *pgid = map.gid; *name_type = map.sid_name_use; } else { + if (pdb_rid_is_user(rid)) + return False; + *pgid = pdb_group_rid_to_gid(rid); *name_type = SID_NAME_ALIAS; } diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index c83f6b3d8d..106d7c1923 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -1443,11 +1443,6 @@ static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid) SAM_ACCOUNT *smbpass=NULL; BOOL ret; - if (!pdb_rid_is_user(user_rid)) { - DEBUG(4,("RID 0x%x is not a user RID\n", user_rid)); - return False; - } - pdb_init_sam(&smbpass); become_root(); @@ -1524,11 +1519,6 @@ static BOOL get_user_info_20(SAM_USER_INFO_20 *id20, uint32 user_rid) SAM_ACCOUNT *sampass=NULL; BOOL ret; - if (!pdb_rid_is_user(user_rid)) { - DEBUG(4,("RID 0x%x is not a user RID\n", user_rid)); - return False; - } - pdb_init_sam(&sampass); become_root(); @@ -1562,11 +1552,6 @@ static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid) SAM_ACCOUNT *sampass=NULL; BOOL ret; - if (!pdb_rid_is_user(user_rid)) { - DEBUG(4,("RID 0x%x is not a user RID\n", user_rid)); - return False; - } - pdb_init_sam(&sampass); become_root(); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 864d3d6c66..ac0b535c13 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -546,9 +546,12 @@ DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) return psid; } } + + /* Make sure we report failure, (when psid == NULL) */ + become_root(); + psid = local_uid_to_sid(psid, uid); + unbecome_root(); - local_uid_to_sid(psid, uid); - DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); return psid; @@ -611,10 +614,14 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) */ if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) { + BOOL result; DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", sid_to_string(sid_str, psid) )); - return local_sid_to_uid(puid, psid, sidtype); + become_root(); + result = local_sid_to_uid(puid, psid, sidtype); + unbecome_root(); + return result; } /* @@ -634,9 +641,13 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) */ if (!winbind_sid_to_uid(puid, psid)) { + BOOL result; DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n", sid_to_string(sid_str, psid) )); - return local_sid_to_uid(puid, psid, sidtype); + become_root(); + result = local_sid_to_uid(puid, psid, sidtype); + unbecome_root(); + return result; } DEBUG(10,("sid_to_uid: winbindd %s -> %u\n", @@ -667,7 +678,6 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", sid_to_string(sid_str, psid) )); - if (!local_sid_to_gid(pgid, psid, sidtype)) { /* this was probably a foreign sid - assume its a group rid and continue */ -- cgit From 3067ec21fb34f46fd1683aad6d455e7d6da8f52e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Apr 2002 03:26:19 +0000 Subject: - added a mangling test suite that measures the collision rate on randomised filenames - fixed several mangling bugs that the test suite pointed out (This used to be commit 858fa7efc34f6e7cdf8500900aed3f7943c91348) --- source3/Makefile.in | 2 +- source3/smbd/mangle_hash2.c | 14 ++++ source3/torture/mangle_test.c | 162 ++++++++++++++++++++++++++++++++++++++++++ source3/torture/torture.c | 28 +++++--- 4 files changed, 194 insertions(+), 12 deletions(-) create mode 100644 source3/torture/mangle_test.c diff --git a/source3/Makefile.in b/source3/Makefile.in index 54e3238fba..476997512f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -364,7 +364,7 @@ NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(UBIQX_OBJ) \ $(LIBSMB_OBJ) $(LIB_OBJ) SMBTORTURE_OBJ = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \ - torture/denytest.o \ + torture/denytest.o torture/mangle_test.o \ $(LIBSMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) MASKTEST_OBJ = torture/masktest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \ diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 96ca7360b8..959a93e07b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -344,6 +344,7 @@ static BOOL check_cache(char *name) /* we found it - construct the full name */ strncpy(extension, name+9, 3); + extension[3] = 0; if (extension[0]) { M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); @@ -435,6 +436,19 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) /* find the '.' if any */ dot_p = strrchr(name, '.'); + if (dot_p) { + /* if the extension contains any illegal characters or + is too long or zero length then we treat it as part + of the prefix */ + for (i=0; i<4 && dot_p[i+1]; i++) { + if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) { + dot_p = NULL; + break; + } + } + if (i == 0 || i == 4) dot_p = NULL; + } + /* the leading character in the mangled name is taken from the first character of the name, if it is ascii otherwise '_' is used diff --git a/source3/torture/mangle_test.c b/source3/torture/mangle_test.c new file mode 100644 index 0000000000..9024925beb --- /dev/null +++ b/source3/torture/mangle_test.c @@ -0,0 +1,162 @@ +/* + Unix SMB/CIFS implementation. + SMB torture tester - mangling test + Copyright (C) Andrew Tridgell 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static TDB_CONTEXT *tdb; + +#define NAME_LENGTH 30 + +static unsigned total, collisions; + +static BOOL test_one(struct cli_state *cli, const char *name) +{ + int fnum; + fstring shortname; + fstring name2; + NTSTATUS status; + TDB_DATA data; + + total++; + + fnum = cli_open(cli, name, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); + if (fnum == -1) { + printf("open of %s failed (%s)\n", name, cli_errstr(cli)); + return False; + } + + if (!cli_close(cli, fnum)) { + printf("close of %s failed (%s)\n", name, cli_errstr(cli)); + return False; + } + + /* get the short name */ + status = cli_qpathinfo_alt_name(cli, name, shortname); + if (!NT_STATUS_IS_OK(status)) { + printf("query altname of %s failed (%s)\n", name, cli_errstr(cli)); + return False; + } + + snprintf(name2, sizeof(name2), "\\mangle_test\\%s", shortname); + if (!cli_unlink(cli, name2)) { + printf("unlink of %s (%s) failed (%s)\n", + name2, name, cli_errstr(cli)); + return False; + } + + /* see if the short name is already in the tdb */ + data = tdb_fetch_by_string(tdb, shortname); + if (data.dptr) { + /* maybe its a duplicate long name? */ + if (strcasecmp(name, data.dptr) != 0) { + /* we have a collision */ + collisions++; + printf("Collision between %s and %s -> %s\n", + name, data.dptr, shortname); + } + free(data.dptr); + } else { + /* store it for later */ + tdb_store_by_string(tdb, shortname, name, strlen(name)+1); + } + + return True; +} + + +static void gen_name(char *name) +{ + const char *chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._-$~"; + unsigned max_idx = strlen(chars); + unsigned len; + int i; + char *p; + + fstrcpy(name, "\\mangle_test\\"); + p = name + strlen(name); + + len = 1 + random() % NAME_LENGTH; + + for (i=0;i Date: Fri, 12 Apr 2002 03:42:44 +0000 Subject: better mangling test. We now test that we can create by long name and delete by short name, and that we can create by short name and delete by long name our old mangling code fails this test. also tweaked the random filename generation to produce more likely collisions (This used to be commit 65609c52960c2b5938150a2fdb5290541f4e0225) --- source3/torture/mangle_test.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/source3/torture/mangle_test.c b/source3/torture/mangle_test.c index 9024925beb..7f05b953c5 100644 --- a/source3/torture/mangle_test.c +++ b/source3/torture/mangle_test.c @@ -22,7 +22,7 @@ static TDB_CONTEXT *tdb; -#define NAME_LENGTH 30 +#define NAME_LENGTH 20 static unsigned total, collisions; @@ -61,6 +61,24 @@ static BOOL test_one(struct cli_state *cli, const char *name) return False; } + /* recreate by short name */ + fnum = cli_open(cli, name2, O_RDWR|O_CREAT|O_EXCL, DENY_NONE); + if (fnum == -1) { + printf("open2 of %s failed (%s)\n", name2, cli_errstr(cli)); + return False; + } + if (!cli_close(cli, fnum)) { + printf("close of %s failed (%s)\n", name, cli_errstr(cli)); + return False; + } + + /* and unlink by long name */ + if (!cli_unlink(cli, name)) { + printf("unlink2 of %s (%s) failed (%s)\n", + name, name2, cli_errstr(cli)); + return False; + } + /* see if the short name is already in the tdb */ data = tdb_fetch_by_string(tdb, shortname); if (data.dptr) { @@ -83,7 +101,7 @@ static BOOL test_one(struct cli_state *cli, const char *name) static void gen_name(char *name) { - const char *chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._-$~"; + const char *chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._-$~..."; unsigned max_idx = strlen(chars); unsigned len; int i; @@ -103,6 +121,19 @@ static void gen_name(char *name) if (strcmp(p, ".") == 0 || strcmp(p, "..") == 0) { p[0] = '_'; } + + /* have a high probability of a common lead char */ + if (random() % 2 == 0) { + p[0] = 'A'; + } + + /* and a high probability of a good extension length */ + if (random() % 2 == 0) { + char *s = strrchr(p, '.'); + if (s) { + s[4] = 0; + } + } } -- cgit From 71c2943d34e6a30819d7c36d7c1d5d5eab2eb968 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Apr 2002 03:54:13 +0000 Subject: nicer measurement of failures and collisions (This used to be commit 61c61f6b4f22c1ef6f837145f5e05730706cc8d4) --- source3/torture/mangle_test.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/source3/torture/mangle_test.c b/source3/torture/mangle_test.c index 7f05b953c5..2d5b3610d5 100644 --- a/source3/torture/mangle_test.c +++ b/source3/torture/mangle_test.c @@ -24,7 +24,7 @@ static TDB_CONTEXT *tdb; #define NAME_LENGTH 20 -static unsigned total, collisions; +static unsigned total, collisions, failures; static BOOL test_one(struct cli_state *cli, const char *name) { @@ -76,7 +76,9 @@ static BOOL test_one(struct cli_state *cli, const char *name) if (!cli_unlink(cli, name)) { printf("unlink2 of %s (%s) failed (%s)\n", name, name2, cli_errstr(cli)); - return False; + failures++; + cli_unlink(cli, name2); + return True; } /* see if the short name is already in the tdb */ @@ -127,6 +129,11 @@ static void gen_name(char *name) p[0] = 'A'; } + /* and a medium probability of a common lead string */ + if (random() % 10 == 0) { + strncpy(p, "ABCDE", 5); + } + /* and a high probability of a good extension length */ if (random() % 2 == 0) { char *s = strrchr(p, '.'); @@ -173,21 +180,22 @@ BOOL torture_mangle(int dummy) break; } if (total && total % 100 == 0) { - printf("collisions %u/%u - %.2f%%\r", - collisions, total, (100.0*collisions) / total); + printf("collisions %u/%u - %.2f%% (%u failures)\r", + collisions, total, (100.0*collisions) / total, failures); } } + cli_unlink(&cli, "\\mangle_test\\*"); if (!cli_rmdir(&cli, "\\mangle_test")) { printf("ERROR: Failed to remove directory\n"); return False; } - printf("\nTotal collisions %u/%u - %.2f%%\n", - collisions, total, (100.0*collisions) / total); + printf("\nTotal collisions %u/%u - %.2f%% (%u failures)\n", + collisions, total, (100.0*collisions) / total, failures); torture_close_connection(&cli); printf("mangle test finished\n"); - return True; + return (failures == 0); } -- cgit