Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)


  14  *    must display the following acknowledgement:
  15  *    This product includes software developed by Boris Popov.
  16  * 4. Neither the name of the author nor the names of any co-contributors
  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $
  33  */



  34 
  35 #include <fcntl.h>
  36 #include <sys/types.h>
  37 #include <sys/queue.h>
  38 #include <sys/stat.h>
  39 
  40 #include <ctype.h>
  41 #include <errno.h>
  42 #include <stdio.h>
  43 #include <string.h>
  44 #include <strings.h>
  45 #include <stdlib.h>
  46 #include <synch.h>
  47 #include <unistd.h>
  48 #include <pwd.h>
  49 #include <libintl.h>
  50 
  51 #include <cflib.h>
  52 #include "rcfile_priv.h"
  53 
  54 #include <assert.h>
  55 
  56 #if 0 /* before SMF */
  57 #define SMB_CFG_FILE    "/etc/nsmb.conf"
  58 #define OLD_SMB_CFG_FILE        "/usr/local/etc/nsmb.conf"
  59 #endif
  60 #define SMBFS_SHARECTL_CMD      "/usr/sbin/sharectl get smbfs"
  61 
  62 extern int smb_debug;
  63 
  64 static struct rcfile *rc_cachelookup(const char *filename);
  65 static struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname);
  66 static struct rcsection *rc_addsect(struct rcfile *rcp, const char *sectname);
  67 static int              rc_freesect(struct rcfile *rcp, struct rcsection *rsp);
  68 static struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *key);
  69 static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name,
  70     const char *value);
  71 static void rc_key_free(struct rckey *p);
  72 static void rc_parse(struct rcfile *rcp);
  73 
  74 /* lock for the variables below */
  75 mutex_t rcfile_mutex = DEFAULTMUTEX;
  76 
  77 SLIST_HEAD(rcfile_head, rcfile);
  78 static struct rcfile_head pf_head = {NULL};
  79 struct rcfile *smb_rc;
  80 int home_nsmbrc;


 130         insecure_nsmbrc = 0;
 131         if (rcp == NULL) {
 132                 return (rc_open(filename, "r", rcfile));
 133         }
 134         f = fopen(filename, "r");
 135         if (f == NULL)
 136                 return (errno);
 137         insecure_nsmbrc = 0;
 138         if (fstat(fileno(f), &statbuf) >= 0 &&
 139             (statbuf.st_mode & 077) != 0)
 140                 insecure_nsmbrc = 1;
 141         t = rcp->rf_f;
 142         rcp->rf_f = f;
 143         rc_parse(rcp);
 144         rcp->rf_f = t;
 145         fclose(f);
 146         return (0);
 147 }
 148 
 149 /*
 150  * Like rc_open, but does popen of command:
 151  * sharectl get smbfs

 152  */
 153 static int
 154 rc_popen_cmd(const char *command, struct rcfile **rcfile)
 155 {
 156         struct rcfile *rcp;
 157         FILE *f;



 158 
 159         assert(MUTEX_HELD(&rcfile_mutex));
 160 
 161         f = popen(command, "r");
 162         if (f == NULL)
 163                 return (errno);
 164         insecure_nsmbrc = 0;

 165 














 166         rcp = malloc(sizeof (struct rcfile));
 167         if (rcp == NULL) {
 168                 fclose(f);
 169                 return (ENOMEM);
 170         }
 171         bzero(rcp, sizeof (struct rcfile));
 172         rcp->rf_name = strdup(command);
 173         rcp->rf_f = f;







 174         SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);

 175         rc_parse(rcp);
 176         *rcfile = rcp;
 177         /* fclose(f) in rc_close */
 178         return (0);












 179 }
 180 

 181 static int
 182 rc_close(struct rcfile *rcp)
 183 {
 184         struct rcsection *p, *n;
 185 
 186         mutex_lock(&rcfile_mutex);
 187 
 188         fclose(rcp->rf_f);



 189         for (p = SLIST_FIRST(&rcp->rf_sect); p; ) {
 190                 n = p;
 191                 p = SLIST_NEXT(p, rs_next);
 192                 rc_freesect(rcp, n);
 193         }
 194         free(rcp->rf_name);
 195         SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next);
 196         free(rcp);
 197 
 198         mutex_unlock(&rcfile_mutex);
 199         return (0);
 200 }
 201 
 202 static struct rcfile *
 203 rc_cachelookup(const char *filename)
 204 {
 205         struct rcfile *p;
 206 
 207         assert(MUTEX_HELD(&rcfile_mutex));
 208 


 326 eval_minauth(char *auth)
 327 {
 328         int i;
 329 
 330         for (i = 0; minauth_values[i]; i++)
 331                 if (strcmp(auth, minauth_values[i]) == 0)
 332                         return (i);
 333         return (-1);
 334 }
 335 
 336 /*
 337  * Ensure that "minauth" is set to the highest level
 338  */
 339 /*ARGSUSED*/
 340 static void
 341 set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp,
 342     char *ptr)
 343 {
 344         int now, new;
 345 #ifdef DEBUG
 346         char *from;
 347 
 348         if (smb_debug)
 349                 from = (home_nsmbrc) ?
 350                     "user file" : "SMF";
 351 #endif
 352 
 353         if (strcmp(rkp->rk_name, "minauth") == 0) {
 354                 now = eval_minauth(rkp->rk_value);
 355                 new = eval_minauth(ptr);
 356                 if (new <= now) {
 357 #ifdef DEBUG
 358                         if (smb_debug)
 359                                 fprintf(stderr,
 360                                     "set_value: rejecting %s=%s"
 361                                     " in %s from %s\n",
 362                                     rkp->rk_name, ptr,
 363                                     rsp->rs_name, from);
 364 #endif
 365                         return;
 366                 }
 367         }
 368 #ifdef DEBUG
 369         if (smb_debug)
 370                 fprintf(stderr,


 644 }
 645 #endif
 646 
 647 /*
 648  * first parse "sharectl get smbfs, then $HOME/.nsmbrc
 649  * This is called by library consumers (commands)
 650  */
 651 int
 652 smb_open_rcfile(char *home)
 653 {
 654         char *fn;
 655         int len, error = 0;
 656 
 657         mutex_lock(&rcfile_mutex);
 658 
 659         smb_rc = NULL;
 660 #if 0   /* before SMF */
 661         fn = SMB_CFG_FILE;
 662         error = rc_open(fn, &smb_rc);
 663 #else
 664         fn = SMBFS_SHARECTL_CMD;
 665         error = rc_popen_cmd(fn, &smb_rc);
 666 #endif
 667         if (error != 0 && error != ENOENT) {
 668                 /* Error from fopen. strerror is OK. */
 669                 fprintf(stderr, dgettext(TEXT_DOMAIN,
 670                     "Can't open %s: %s\n"), fn, strerror(errno));
 671         }
 672 #ifdef DEBUG
 673         if (smb_debug)
 674                 dump_props(fn);
 675 #endif
 676 
 677         if (home) {
 678                 len = strlen(home) + 20;
 679                 fn = malloc(len);
 680                 snprintf(fn, len, "%s/.nsmbrc", home);
 681                 home_nsmbrc = 1;
 682                 error = rc_merge(fn, &smb_rc);
 683                 if (error != 0 && error != ENOENT) {
 684                         fprintf(stderr, dgettext(TEXT_DOMAIN,
 685                             "Can't open %s: %s\n"), fn, strerror(errno));




  14  *    must display the following acknowledgement:
  15  *    This product includes software developed by Boris Popov.
  16  * 4. Neither the name of the author nor the names of any co-contributors
  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $
  33  */
  34 /*
  35  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  36  */
  37 
  38 #include <fcntl.h>
  39 #include <sys/types.h>
  40 #include <sys/queue.h>
  41 #include <sys/stat.h>
  42 
  43 #include <ctype.h>
  44 #include <errno.h>
  45 #include <stdio.h>
  46 #include <string.h>
  47 #include <strings.h>
  48 #include <stdlib.h>
  49 #include <synch.h>
  50 #include <unistd.h>
  51 #include <pwd.h>
  52 #include <libintl.h>
  53 
  54 #include <cflib.h>
  55 #include "rcfile_priv.h"
  56 
  57 #include <assert.h>
  58 
  59 #if 0 /* before SMF */
  60 #define SMB_CFG_FILE    "/etc/nsmb.conf"
  61 #define OLD_SMB_CFG_FILE        "/usr/local/etc/nsmb.conf"
  62 #endif

  63 
  64 extern int smb_debug;
  65 
  66 static struct rcfile *rc_cachelookup(const char *filename);
  67 static struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname);
  68 static struct rcsection *rc_addsect(struct rcfile *rcp, const char *sectname);
  69 static int              rc_freesect(struct rcfile *rcp, struct rcsection *rsp);
  70 static struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *key);
  71 static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name,
  72     const char *value);
  73 static void rc_key_free(struct rckey *p);
  74 static void rc_parse(struct rcfile *rcp);
  75 
  76 /* lock for the variables below */
  77 mutex_t rcfile_mutex = DEFAULTMUTEX;
  78 
  79 SLIST_HEAD(rcfile_head, rcfile);
  80 static struct rcfile_head pf_head = {NULL};
  81 struct rcfile *smb_rc;
  82 int home_nsmbrc;


 132         insecure_nsmbrc = 0;
 133         if (rcp == NULL) {
 134                 return (rc_open(filename, "r", rcfile));
 135         }
 136         f = fopen(filename, "r");
 137         if (f == NULL)
 138                 return (errno);
 139         insecure_nsmbrc = 0;
 140         if (fstat(fileno(f), &statbuf) >= 0 &&
 141             (statbuf.st_mode & 077) != 0)
 142                 insecure_nsmbrc = 1;
 143         t = rcp->rf_f;
 144         rcp->rf_f = f;
 145         rc_parse(rcp);
 146         rcp->rf_f = t;
 147         fclose(f);
 148         return (0);
 149 }
 150 
 151 /*
 152  * Like rc_open, but creates a temporary file and
 153  * reads the sharectl settings into it.
 154  * The file is deleted when we close it.
 155  */
 156 static int
 157 rc_open_sharectl(struct rcfile **rcfile)
 158 {
 159         static char template[24] = "/tmp/smbfsXXXXXX";
 160         struct rcfile *rcp = NULL;
 161         FILE *fp = NULL;
 162         int err;
 163         int fd = -1;
 164 
 165         assert(MUTEX_HELD(&rcfile_mutex));
 166 
 167         fd = mkstemp(template);
 168         if (fd < 0) {
 169                 err = errno;
 170                 goto errout;
 171         }
 172 
 173         fp = fdopen(fd, "w+");
 174         if (fp == NULL) {
 175                 err = errno;
 176                 close(fd);
 177                 goto errout;
 178         }
 179         fd = -1; /* The fp owns this fd now. */
 180 
 181         /*
 182          * Get smbfs sharectl settings into the file.
 183          */
 184         if ((err = rc_scf_get_sharectl(fp)) != 0)
 185                 goto errout;
 186 
 187         rcp = malloc(sizeof (struct rcfile));
 188         if (rcp == NULL) {
 189                 err = ENOMEM;
 190                 goto errout;
 191         }
 192         bzero(rcp, sizeof (struct rcfile));
 193 
 194         rcp->rf_name = strdup(template);
 195         if (rcp->rf_name == NULL) {
 196                 err = ENOMEM;
 197                 goto errout;
 198         }
 199         rcp->rf_f = fp;
 200         rcp->rf_flags = RCFILE_DELETE_ON_CLOSE;
 201 
 202         SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
 203         insecure_nsmbrc = 0;
 204         rc_parse(rcp);
 205         *rcfile = rcp;
 206         /* fclose(f) in rc_close */
 207         return (0);
 208 
 209 errout:
 210         if (rcp != NULL)
 211                 free(rcp);
 212         if (fp != NULL) {
 213                 fclose(fp);
 214                 fd = -1;
 215         }
 216         if (fd != -1)
 217                 close(fd);
 218 
 219         return (err);
 220 }
 221 
 222 
 223 static int
 224 rc_close(struct rcfile *rcp)
 225 {
 226         struct rcsection *p, *n;
 227 
 228         mutex_lock(&rcfile_mutex);
 229 
 230         fclose(rcp->rf_f);
 231         if (rcp->rf_flags & RCFILE_DELETE_ON_CLOSE)
 232                 (void) unlink(rcp->rf_name);
 233 
 234         for (p = SLIST_FIRST(&rcp->rf_sect); p; ) {
 235                 n = p;
 236                 p = SLIST_NEXT(p, rs_next);
 237                 rc_freesect(rcp, n);
 238         }
 239         free(rcp->rf_name);
 240         SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next);
 241         free(rcp);
 242 
 243         mutex_unlock(&rcfile_mutex);
 244         return (0);
 245 }
 246 
 247 static struct rcfile *
 248 rc_cachelookup(const char *filename)
 249 {
 250         struct rcfile *p;
 251 
 252         assert(MUTEX_HELD(&rcfile_mutex));
 253 


 371 eval_minauth(char *auth)
 372 {
 373         int i;
 374 
 375         for (i = 0; minauth_values[i]; i++)
 376                 if (strcmp(auth, minauth_values[i]) == 0)
 377                         return (i);
 378         return (-1);
 379 }
 380 
 381 /*
 382  * Ensure that "minauth" is set to the highest level
 383  */
 384 /*ARGSUSED*/
 385 static void
 386 set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp,
 387     char *ptr)
 388 {
 389         int now, new;
 390 #ifdef DEBUG
 391         char *from = "SMF";
 392 
 393         if (home_nsmbrc != 0)
 394                 from = "user file";

 395 #endif
 396 
 397         if (strcmp(rkp->rk_name, "minauth") == 0) {
 398                 now = eval_minauth(rkp->rk_value);
 399                 new = eval_minauth(ptr);
 400                 if (new <= now) {
 401 #ifdef DEBUG
 402                         if (smb_debug)
 403                                 fprintf(stderr,
 404                                     "set_value: rejecting %s=%s"
 405                                     " in %s from %s\n",
 406                                     rkp->rk_name, ptr,
 407                                     rsp->rs_name, from);
 408 #endif
 409                         return;
 410                 }
 411         }
 412 #ifdef DEBUG
 413         if (smb_debug)
 414                 fprintf(stderr,


 688 }
 689 #endif
 690 
 691 /*
 692  * first parse "sharectl get smbfs, then $HOME/.nsmbrc
 693  * This is called by library consumers (commands)
 694  */
 695 int
 696 smb_open_rcfile(char *home)
 697 {
 698         char *fn;
 699         int len, error = 0;
 700 
 701         mutex_lock(&rcfile_mutex);
 702 
 703         smb_rc = NULL;
 704 #if 0   /* before SMF */
 705         fn = SMB_CFG_FILE;
 706         error = rc_open(fn, &smb_rc);
 707 #else
 708         fn = "(sharectl get smbfs)";
 709         error = rc_open_sharectl(&smb_rc);
 710 #endif
 711         if (error != 0 && error != ENOENT) {
 712                 /* Error from fopen. strerror is OK. */
 713                 fprintf(stderr, dgettext(TEXT_DOMAIN,
 714                     "Can't open %s: %s\n"), fn, strerror(errno));
 715         }
 716 #ifdef DEBUG
 717         if (smb_debug)
 718                 dump_props(fn);
 719 #endif
 720 
 721         if (home) {
 722                 len = strlen(home) + 20;
 723                 fn = malloc(len);
 724                 snprintf(fn, len, "%s/.nsmbrc", home);
 725                 home_nsmbrc = 1;
 726                 error = rc_merge(fn, &smb_rc);
 727                 if (error != 0 && error != ENOENT) {
 728                         fprintf(stderr, dgettext(TEXT_DOMAIN,
 729                             "Can't open %s: %s\n"), fn, strerror(errno));