I asked about this ability a few weeks ago and the reply was basically that folks would be interested in seeing it happen. Well, the client insisted, so I've put together a hack that accomplishes it. The basic design requirement was that users would not see files/directories that they did not have at least read access to. This request came about because we were migrating from a Novell server, and this is apparently the default behaviour for Netware. This hack was implemented on a FreeBSD 4.2-STABLE box using samba 2.0.7, and it has been working predictably for about a week. A few coding notes: 1. I'm not too sure about the size of fullPath. 2048 seemed a value that wouldn't normally be exceeded, but I don't have any proof that it's a good size. It may be too large or too small (compared to system limits, of course) In the final analysis, it should be the same size as the max path size of the system it's running on. 2. This a pretty much a hack. It should really be implemented as a config option, possibly with per-share capibilities. As it stands, modifying dir.c and recompiling turns this on for everything, period. 3. The access() command is considered "a security hole that should never be used" by the BSD documentation. However, I can not see how access() is a security concern _in this particular implementation_, and nobody has been able to give me an example of how it could be. If using access() makes you nervious, you could replace it with open()-with a test for success. I didn't want to do this because of the potential performance hit. Also, I don't know whether or not access() is portable to other systems (such as Linux) So, the upshot of the story is to replace the function OpenDir() in dir.c with the one shown below, recompile and you'll find that machines connected via samba will no longer be able to see files/directories listed that they do not have read rights to. (yes, I know I could have sent diffs, but this change was made *after* FreeBSD specific patches were applied to the samba source, and I don't know how that would affect a diff) Hope this is useful to people. -Bill void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; DIR *p = dos_opendir(name); int used=0; char *fullPath; if (!p) return(NULL); dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { closedir(p); return(NULL); } fullPath = (char *)malloc(2048); if (!fullPath) { closedir(p); return(NULL); } dirp->pos = dirp->numentries = dirp->mallocsize = 0; dirp->data = dirp->current = NULL; while ((n = dos_readdirname(p))) { int l = strlen(n)+1; /* If it's a vetoed file, pretend it doesn't even exist */ if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; /* hack to hide files that the user doesn't have read perms to */ snprintf(fullPath,2048,"%s/%s/%s",conn->origpath,name,n); if (access(fullPath,R_OK) ) continue; if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; r = (char *)Realloc(dirp->data,s); if (!r) { DEBUG(0,("Out of memory in OpenDir\n")); break; } dirp->data = r; dirp->mallocsize = s; dirp->current = dirp->data; } pstrcpy(dirp->data+used,n); used += l; dirp->numentries++; } closedir(p); return((void *)dirp); }
Bill Moran wrote:> 1. I'm not too sure about the size of fullPath. 2048 seemed a value that > wouldn't normally be exceeded, but I don't have any proof that it's a > good size. It may be too large or too small (compared to system limits, > of course) In the final analysis, it should be the same size as the max > path size of the system it's running on.This can be discovered with pathconf(), hopefull mentioned in /usr/include/unistd.h otherewise the data is buried in <limits.h> or <unistd.h>. Solaris uses 1024, Posxz 255. --dave -- David Collier-Brown, | Always do right. This will gratify Performance & Engineering Team | some people and astonish the rest. Americas Customer Engineering | -- Mark Twain (905) 415-2849 | davecb@canada.sun.com
>I asked about this ability a few weeks ago and the reply was basically >that folks would be interested in seeing it happen. Well, the client >insisted, so I've put together a hack that accomplishes it. >The basic design requirement was that users would not see >files/directories that they did not have at least read access to. This >request came about because we were migrating from a Novell server, and >this is apparently the default behaviour for Netware. >This hack was implemented on a FreeBSD 4.2-STABLE box using samba 2.0.7, >and it has been working predictably for about a week.Well done!>A few coding notes:me too :-)>1. I'm not too sure about the size of fullPath. 2048 seemed a value that >wouldn't normally be exceeded, but I don't have any proof that it's a >good size. It may be too large or too small (compared to system limits, >of course) In the final analysis, it should be the same size as the max >path size of the system it's running on.How about a getcwd(), chdir() to the directory, loop, and chdir() back? Thus one can avoid the pasting of filenames together. And getcwd() at least allows to check if a larger buffer is needed. (if the current directory of samba is normally /, this can even be avoided - simple do chdir(), loop, chdir(/)).>2. This a pretty much a hack. It should really be implemented as a >config option, possibly with per-share capibilities. As it stands, >modifying dir.c and recompiling turns this on for everything, period.>3. The access() command is considered "a security hole that should never >be used" by the BSD documentation. However, I can not see how access() >is a security concern _in this particular implementation_, and nobody >has been able to give me an example of how it could be. If using >access() makes you nervious, you could replace it with open()-with a >test for success. I didn't want to do this because of the potential >performance hit. Also, I don't know whether or not access() is portable >to other systems (such as Linux)I don't know about this security hole. Do you have some documentation about it?>So, the upshot of the story is to replace the function OpenDir() in >dir.c with the one shown below, recompile and you'll find that machines >connected via samba will no longer be able to see files/directories >listed that they do not have read rights to. >(yes, I know I could have sent diffs, but this change was made *after* >FreeBSD specific patches were applied to the samba source, and I don't >know how that would affect a diff) > >Hope this is useful to people. >-BillThanks very much, Bill! I'll try to test that. Regards, Phil
>Race condition. If you use access() to test permissions - then perform >some function as a result, there's a possibility for someone to change >the permissions between those two actions. For example, you test >access() to see if the user can open a file and find it OK to open, then >a malicious user replaces the file with a links to passwd. You then have >access to a file you shouldn't. Like I said, doesn't seem to apply in >this use.Well, with a network file system many strange things can happen ... Still ... I can't see how it would do anything worse than show a file that the user really doesn't have access to, then deny access when they try to read the file. If you can think of a scenerio where it could be a problem, I'd like to hear it. -Bill
Still don't understand how you could bring this about with the code change I made in dir.c -Bill>the user could make the admin kill the server if he links a file to >/etc/passwd and the admin runs his smbd as root...
Apparently Analagous Threads
- [PATCH 4/5][REPOST][BTRFS-PROGS] Avoid to scan cdrom and floppy
- [PATCH 1/3] klibc: Add scandir() and alphasort() support.
- [PATCH-resend] Implement SSH2_FXF_APPEND
- ftp-server patch - restrict user to directory
- supporting --fake-super on opensolaris (zfs) destination