From: Jeremy Allison Date: Sat, 27 Mar 2010 00:09:58 +0000 (-0700) Subject: Fix bug #7240 - Net usershare is not case sensitive. X-Git-Tag: samba-3.6.0pre1~3971 X-Git-Url: http://git.samba.org/samba.git/?p=sfrench%2Fsamba-autobuild%2F.git;a=commitdiff_plain;h=fac8ca52ade6e490eea3cf3d0fc98287da321c13 Fix bug #7240 - Net usershare is not case sensitive. Updates usershare files in a backwards compatible way. I don't intend to back port this fix to 3.5.x as it depends on a version upgrade in the share_info.tdb share security database. Jeremy. --- diff --git a/source3/include/proto.h b/source3/include/proto.h index ecb29618aee..7cc211b05a1 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4318,6 +4318,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, int numlines, char **pp_sharepath, char **pp_comment, + char **pp_cp_share_name, SEC_DESC **ppsd, bool *pallow_guest); int load_usershare_service(const char *servicename); diff --git a/source3/include/smb.h b/source3/include/smb.h index 52b98431561..751f3a46a4b 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1921,7 +1921,9 @@ enum usershare_err { USERSHARE_PATH_IS_DENIED, USERSHARE_PATH_NOT_ALLOWED, USERSHARE_PATH_NOT_DIRECTORY, - USERSHARE_POSIX_ERR + USERSHARE_POSIX_ERR, + USERSHARE_MALFORMED_SHARENAME_DEF, + USERSHARE_BAD_SHARENAME }; /* Different reasons for closing a file. */ diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 9e9930f7d48..c7497c4d04c 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -8514,6 +8514,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, int numlines, char **pp_sharepath, char **pp_comment, + char **pp_cp_servicename, SEC_DESC **ppsd, bool *pallow_guest) { @@ -8581,6 +8582,27 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, if (lines[4][9] == 'y') { *pallow_guest = True; } + + /* Backwards compatible extension to file version #2. */ + if (numlines > 5) { + if (strncmp(lines[5], "sharename=", 10) != 0) { + return USERSHARE_MALFORMED_SHARENAME_DEF; + } + if (!strequal(&lines[5][10], servicename)) { + return USERSHARE_BAD_SHARENAME; + } + *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]); + if (!*pp_cp_servicename) { + return USERSHARE_POSIX_ERR; + } + } + } + + if (*pp_cp_servicename == NULL) { + *pp_cp_servicename = talloc_strdup(ctx, servicename); + if (!*pp_cp_servicename) { + return USERSHARE_POSIX_ERR; + } } if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) { @@ -8692,26 +8714,34 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i char *fname = NULL; char *sharepath = NULL; char *comment = NULL; - fstring service_name; + char *cp_service_name = NULL; char **lines = NULL; int numlines = 0; int fd = -1; int iService = -1; - TALLOC_CTX *ctx = NULL; + TALLOC_CTX *ctx = talloc_stackframe(); SEC_DESC *psd = NULL; bool guest_ok = False; + char *canon_name = NULL; + bool added_service = false; + int ret = -1; /* Ensure share name doesn't contain invalid characters. */ if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) { DEBUG(0,("process_usershare_file: share name %s contains " "invalid characters (any of %s)\n", file_name, INVALID_SHARENAME_CHARS )); - return -1; + goto out; } - fstrcpy(service_name, file_name); + canon_name = canonicalize_servicename(ctx, file_name); + if (!canon_name) { + goto out; + } - if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) { + fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name); + if (!fname) { + goto out; } /* Minimize the race condition by doing an lstat before we @@ -8720,19 +8750,16 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i if (sys_lstat(fname, &lsbuf, false) != 0) { DEBUG(0,("process_usershare_file: stat of %s failed. %s\n", fname, strerror(errno) )); - SAFE_FREE(fname); - return -1; + goto out; } /* This must be a regular file, not a symlink, directory or other strange filetype. */ if (!check_usershare_stat(fname, &lsbuf)) { - SAFE_FREE(fname); - return -1; + goto out; } { - char *canon_name = canonicalize_servicename(talloc_tos(), service_name); TDB_DATA data = dbwrap_fetch_bystring( ServiceHash, canon_name, canon_name); @@ -8741,7 +8768,6 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) { iService = *(int *)data.dptr; } - TALLOC_FREE(canon_name); } if (iService != -1 && @@ -8749,10 +8775,10 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i &lsbuf.st_ex_mtime) == 0) { /* Nothing changed - Mark valid and return. */ DEBUG(10,("process_usershare_file: service %s not changed.\n", - service_name )); + canon_name )); ServicePtrs[iService]->usershare = USERSHARE_VALID; - SAFE_FREE(fname); - return iService; + ret = iService; + goto out; } /* Try and open the file read only - no symlinks allowed. */ @@ -8765,8 +8791,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i if (fd == -1) { DEBUG(0,("process_usershare_file: unable to open %s. %s\n", fname, strerror(errno) )); - SAFE_FREE(fname); - return -1; + goto out; } /* Now fstat to be *SURE* it's a regular file. */ @@ -8774,8 +8799,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i close(fd); DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n", fname, strerror(errno) )); - SAFE_FREE(fname); - return -1; + goto out; } /* Is it the same dev/inode as was lstated ? */ @@ -8783,15 +8807,13 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i close(fd); DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. " "Symlink spoofing going on ?\n", fname )); - SAFE_FREE(fname); - return -1; + goto out; } /* This must be a regular file, not a symlink, directory or other strange filetype. */ if (!check_usershare_stat(fname, &sbuf)) { - SAFE_FREE(fname); - return -1; + goto out; } lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL); @@ -8800,29 +8822,16 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i if (lines == NULL) { DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n", fname, (unsigned int)sbuf.st_ex_uid )); - SAFE_FREE(fname); - return -1; - } - - SAFE_FREE(fname); - - /* Should we allow printers to be shared... ? */ - ctx = talloc_init("usershare_sd_xctx"); - if (!ctx) { - TALLOC_FREE(lines); - return 1; + goto out; } - if (parse_usershare_file(ctx, &sbuf, service_name, + if (parse_usershare_file(ctx, &sbuf, file_name, iService, lines, numlines, &sharepath, - &comment, &psd, &guest_ok) != USERSHARE_OK) { - talloc_destroy(ctx); - TALLOC_FREE(lines); - return -1; + &comment, &cp_service_name, + &psd, &guest_ok) != USERSHARE_OK) { + goto out; } - TALLOC_FREE(lines); - /* Everything ok - add the service possibly using a template. */ if (iService < 0) { const struct service *sp = &sDefault; @@ -8830,25 +8839,24 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i sp = ServicePtrs[snum_template]; } - if ((iService = add_a_service(sp, service_name)) < 0) { + if ((iService = add_a_service(sp, cp_service_name)) < 0) { DEBUG(0, ("process_usershare_file: Failed to add " - "new service %s\n", service_name)); - talloc_destroy(ctx); - return -1; + "new service %s\n", cp_service_name)); + goto out; } + added_service = true; + /* Read only is controlled by usershare ACL below. */ ServicePtrs[iService]->bRead_only = False; } /* Write the ACL of the new/modified share. */ - if (!set_share_security(service_name, psd)) { + if (!set_share_security(canon_name, psd)) { DEBUG(0, ("process_usershare_file: Failed to set share " "security for user share %s\n", - service_name )); - lp_remove_service(iService); - talloc_destroy(ctx); - return -1; + canon_name )); + goto out; } /* If from a template it may be marked invalid. */ @@ -8867,9 +8875,17 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i string_set(&ServicePtrs[iService]->szPath, sharepath); string_set(&ServicePtrs[iService]->comment, comment); - talloc_destroy(ctx); + ret = iService; + + out: - return iService; + if (ret == -1 && iService != -1 && added_service) { + lp_remove_service(iService); + } + + TALLOC_FREE(lines); + TALLOC_FREE(ctx); + return ret; } /*************************************************************************** diff --git a/source3/utils/net_usershare.c b/source3/utils/net_usershare.c index 7a688c1330b..05b3cbd0151 100644 --- a/source3/utils/net_usershare.c +++ b/source3/utils/net_usershare.c @@ -37,6 +37,8 @@ struct { {N_("Path not allowed"), USERSHARE_PATH_NOT_ALLOWED}, {N_("Path is not a directory"), USERSHARE_PATH_NOT_DIRECTORY}, {N_("System error"), USERSHARE_POSIX_ERR}, + {N_("Malformed sharename definition"), USERSHARE_MALFORMED_SHARENAME_DEF}, + {N_("Bad sharename (doesn't match filename)"), USERSHARE_BAD_SHARENAME}, {NULL,(enum usershare_err)-1} }; @@ -332,6 +334,7 @@ static int info_fn(struct file_list *fl, void *priv) char *basepath; char *sharepath = NULL; char *comment = NULL; + char *cp_sharename = NULL; char *acl_str; int num_aces; char sep_str[2]; @@ -392,6 +395,7 @@ static int info_fn(struct file_list *fl, void *priv) us_err = parse_usershare_file(ctx, &sbuf, fl->pathname, -1, lines, numlines, &sharepath, &comment, + &cp_sharename, &psd, &guest_ok); @@ -473,13 +477,13 @@ static int info_fn(struct file_list *fl, void *priv) /* NOTE: This is smb.conf-like output. Do not translate. */ if (pi->op == US_INFO_OP) { - d_printf("[%s]\n", fl->pathname ); + d_printf("[%s]\n", cp_sharename ); d_printf("path=%s\n", sharepath ); d_printf("comment=%s\n", comment); d_printf("%s\n", acl_str); d_printf("guest_ok=%c\n\n", guest_ok ? 'y' : 'n'); } else if (pi->op == US_LIST_OP) { - d_printf("%s\n", fl->pathname); + d_printf("%s\n", cp_sharename); } return 0; @@ -617,6 +621,7 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) SMB_STRUCT_STAT sbuf; SMB_STRUCT_STAT lsbuf; char *sharename; + const char *cp_sharename; char *full_path; char *full_path_tmp; const char *us_path; @@ -645,21 +650,25 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) default: return net_usershare_add_usage(c, argc, argv); case 2: + cp_sharename = argv[0]; sharename = strlower_talloc(ctx, argv[0]); us_path = argv[1]; break; case 3: + cp_sharename = argv[0]; sharename = strlower_talloc(ctx, argv[0]); us_path = argv[1]; us_comment = argv[2]; break; case 4: + cp_sharename = argv[0]; sharename = strlower_talloc(ctx, argv[0]); us_path = argv[1]; us_comment = argv[2]; arg_acl = argv[3]; break; case 5: + cp_sharename = argv[0]; sharename = strlower_talloc(ctx, argv[0]); us_path = argv[1]; us_comment = argv[2]; @@ -929,8 +938,14 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) /* Create the in-memory image of the file. */ file_img = talloc_strdup(ctx, "#VERSION 2\npath="); - file_img = talloc_asprintf_append(file_img, "%s\ncomment=%s\nusershare_acl=%s\nguest_ok=%c\n", - us_path, us_comment, us_acl, guest_ok ? 'y' : 'n'); + file_img = talloc_asprintf_append(file_img, + "%s\ncomment=%s\nusershare_acl=%s\n" + "guest_ok=%c\nsharename=%s\n", + us_path, + us_comment, + us_acl, + guest_ok ? 'y' : 'n', + cp_sharename); to_write = strlen(file_img);