allow-home-share-as-usershare [plain text]
Index: samba/source/utils/net_usershare.c
===================================================================
--- samba/source/utils/net_usershare.c.orig
+++ samba/source/utils/net_usershare.c
@@ -518,6 +518,33 @@ static int count_num_usershares(void)
Add a single userlevel share.
***************************************************************************/
+static BOOL usershare_name_is_valid(const char *sharename)
+{
+ struct passwd *pwent;
+ uid_t uid;
+
+ if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
+ d_fprintf(stderr, "net usershare add: share name %s contains "
+ "invalid characters (any of %s)\n",
+ sharename, INVALID_SHARENAME_CHARS);
+ return False;
+ }
+
+ /* Disallow shares the same as users unless the share is being added by
+ * root or by the user themselves.
+ */
+ uid = getuid();
+ if (uid != 0 &&
+ (pwent = getpwnam(sharename)) &&
+ pwent->pw_uid != uid) {
+ d_fprintf(stderr, "net usershare add: share name %s is "
+ "already a valid system user name\n", sharename );
+ return False;
+ }
+
+ return True;
+}
+
static int net_usershare_add(int argc, const char **argv)
{
TALLOC_CTX *ctx = NULL;
@@ -598,18 +625,7 @@ static int net_usershare_add(int argc, c
return -1;
}
- if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
- d_fprintf(stderr, "net usershare add: share name %s contains "
- "invalid characters (any of %s)\n",
- sharename, INVALID_SHARENAME_CHARS);
- SAFE_FREE(sharename);
- return -1;
- }
-
- /* Disallow shares the same as users. */
- if (getpwnam(sharename)) {
- d_fprintf(stderr, "net usershare add: share name %s is already a valid system user name\n",
- sharename );
+ if (!usershare_name_is_valid(sharename)) {
SAFE_FREE(sharename);
return -1;
}
Index: samba/source/param/loadparm.c
===================================================================
--- samba/source/param/loadparm.c.orig
+++ samba/source/param/loadparm.c
@@ -4332,8 +4332,11 @@ static void set_allowed_client_auth(void
get their sorry ass fired.
***************************************************************************/
-static BOOL check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
+static BOOL check_usershare_stat(const char *service_name,
+ const char *fname, SMB_STRUCT_STAT *psbuf)
{
+ struct passwd *pwent;
+
if (!S_ISREG(psbuf->st_mode)) {
DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
"not a regular file\n",
@@ -4358,6 +4361,22 @@ static BOOL check_usershare_stat(const c
return False;
}
+ /* Only root and the user themselves are allowed to create a user share
+ * named after a user. This prevents users clobbering each others'
+ * auto-home shares.
+ *
+ * NOTE: this check will not be 100% because getpwnam is case-sensitive
+ * on some systems.
+ */
+ if ((pwent = sys_getpwnam(service_name))) {
+ if (psbuf->st_uid != 0 && psbuf->st_uid != pwent->pw_uid) {
+ DEBUG(0, ("check_usershare_stat: file %s is a home "
+ "share for %s, but is owned by uid %u.\n",
+ fname, service_name, (unsigned int)psbuf->st_uid));
+ return False;
+ }
+ }
+
return True;
}
@@ -4568,15 +4587,17 @@ static int process_usershare_file(const
return -1;
}
+ canonicalize_servicename(service_name);
+
/* This must be a regular file, not a symlink, directory or
other strange filetype. */
- if (!check_usershare_stat(fname, &lsbuf)) {
+ if (!check_usershare_stat(service_name, fname, &lsbuf)) {
return -1;
}
/* See if there is already a servicenum for this name. */
/* tdb_fetch_int32 returns -1 if not found. */
- iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
+ iService = (int)tdb_fetch_int32(ServiceHash, service_name);
if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
/* Nothing changed - Mark valid and return. */
@@ -4617,7 +4638,7 @@ static int process_usershare_file(const
/* This must be a regular file, not a symlink, directory or
other strange filetype. */
- if (!check_usershare_stat(fname, &sbuf)) {
+ if (!check_usershare_stat(service_name, fname, &sbuf)) {
return -1;
}
Index: samba/source/smbd/service.c
===================================================================
--- samba/source/smbd/service.c.orig
+++ samba/source/smbd/service.c
@@ -269,6 +269,15 @@ int find_service(fstring service)
iService = lp_servicenumber(service);
+ /* Is it a usershare service ? Usershares are statically configured
+ * services, so they get priority over any implicitly created services.
+ */
+ if (iService < 0 && *lp_usershare_path()) {
+ /* Ensure the name is canonicalized. */
+ strlower_m(service);
+ iService = load_usershare_service(service);
+ }
+
/* now handle the special case of a home directory */
if (iService < 0) {
char *phome_dir = get_user_home_dir(service);
@@ -312,13 +321,6 @@ int find_service(fstring service)
if (iService < 0) {
}
- /* Is it a usershare service ? */
- if (iService < 0 && *lp_usershare_path()) {
- /* Ensure the name is canonicalized. */
- strlower_m(service);
- iService = load_usershare_service(service);
- }
-
/* just possibly it's a default service? */
if (iService < 0) {
char *pdefservice = lp_defaultservice();