root/source4/client/mount.cifs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mount_cifs_usage
  2. getusername
  3. parse_cifs_url
  4. parse_options
  5. parse_server
  6. main

   1 #define _GNU_SOURCE
   2 
   3 #include <stdlib.h>
   4 #include <unistd.h>
   5 #include <pwd.h>
   6 #include <sys/types.h>
   7 #include <sys/mount.h>
   8 #include <sys/stat.h>
   9 #include <sys/utsname.h>
  10 #include <sys/socket.h>
  11 #include <arpa/inet.h>
  12 #include <getopt.h>
  13 #include <errno.h>
  14 #include <netdb.h>
  15 #include <string.h>
  16 #include <mntent.h>
  17 
  18 #define MOUNT_CIFS_VERSION "1"
  19 
  20 extern char *getusername(void);
  21 
  22 char * thisprogram;
  23 int verboseflag = 0;
  24 static int got_password = 0;
  25 static int got_user = 0;
  26 static int got_domain = 0;
  27 static int got_ip = 0;
  28 static int got_unc = 0;
  29 static int got_uid = 0;
  30 static int got_gid = 0;
  31 static char * user_name = NULL;
  32 char * mountpassword = NULL;
  33 
  34 
  35 void mount_cifs_usage()
     /* [<][>][^][v][top][bottom][index][help] */
  36 {
  37         printf("\nUsage:  %s remotetarget dir\n", thisprogram);
  38         printf("\nMount the remotetarget, specified as either a UNC name or ");
  39         printf(" CIFS URL, to the local directory, dir.\n");
  40 
  41         exit(1);
  42 }
  43 
  44 /* caller frees username if necessary */
  45 char * getusername() {
     /* [<][>][^][v][top][bottom][index][help] */
  46         char *username = NULL;
  47         struct passwd *password = getpwuid(getuid());
  48 
  49         if (password) {
  50                 username = password->pw_name;
  51         }
  52         return username;
  53 }
  54 
  55 char * parse_cifs_url(unc_name)
     /* [<][>][^][v][top][bottom][index][help] */
  56 {
  57         printf("\ncifs url %s\n",unc_name);
  58 }
  59 
  60 int parse_options(char * options)
     /* [<][>][^][v][top][bottom][index][help] */
  61 {
  62         char * data;
  63         char * value = 0;
  64 
  65         if (!options)
  66                 return 1;
  67 
  68         while ((data = strsep(&options, ",")) != NULL) {
  69                 if (!*data)
  70                         continue;
  71                 if ((value = strchr(data, '=')) != NULL) {
  72                         *value++ = '\0';
  73                 }
  74                 if (strncmp(data, "user", 4) == 0) {
  75                         if (!value || !*value) {
  76                                 printf("invalid or missing username\n");
  77                                 return 1;       /* needs_arg; */
  78                         }
  79                         if (strnlen(value, 260) < 260) {
  80                                 got_user=1;
  81                                 /* BB add check for format user%pass */
  82                                 /* if(strchr(username%passw) got_password = 1) */
  83                         } else {
  84                                 printf("username too long\n");
  85                                 return 1;
  86                         }
  87         } else if (strncmp(data, "pass", 4) == 0) {
  88                 if (!value || !*value) {
  89                         if(got_password) {
  90                                 printf("password specified twice, ignoring second\n");
  91                         } else
  92                                 got_password = 1;
  93                 } else if (strnlen(value, 17) < 17) {
  94                         got_password = 1;
  95                 } else {
  96                         printf("password too long\n");
  97                         return 1;
  98                 }
  99         } else if (strncmp(data, "ip", 2) == 0) {
 100                 if (!value || !*value) {
 101                         printf("target ip address argument missing");
 102                 } else if (strnlen(value, 35) < 35) {
 103                         got_ip = 1;
 104                 } else {
 105                         printf("ip address too long\n");
 106                         return 1;
 107                 }
 108         } else if ((strncmp(data, "unc", 3) == 0)
 109                    || (strncmp(data, "target", 6) == 0)
 110                    || (strncmp(data, "path", 4) == 0)) {
 111                 if (!value || !*value) {
 112                         printf("invalid path to network resource\n");
 113                         return 1;  /* needs_arg; */
 114                 } else if(strnlen(value,5) < 5) {
 115                         printf("UNC name too short");
 116                 }
 117 
 118                 if (strnlen(value, 300) < 300) {
 119                         got_unc = 1;
 120                         if (strncmp(value, "//", 2) == 0) {
 121                                 if(got_unc)
 122                                         printf("unc name specified twice, ignoring second\n");
 123                                 else
 124                                         got_unc = 1;
 125                         } else if (strncmp(value, "\\\\", 2) != 0) {                       
 126                                 printf("UNC Path does not begin with // or \\\\ \n");
 127                                 return 1;
 128                         } else {
 129                                 if(got_unc)
 130                                         printf("unc name specified twice, ignoring second\n");
 131                                 else
 132                                         got_unc = 1;
 133                         }
 134                 } else {
 135                         printf("CIFS: UNC name too long\n");
 136                         return 1;
 137                 }
 138         } else if ((strncmp(data, "domain", 3) == 0)
 139                    || (strncmp(data, "workgroup", 5) == 0)) {
 140                 if (!value || !*value) {
 141                         printf("CIFS: invalid domain name\n");
 142                         return 1;       /* needs_arg; */
 143                 }
 144                 if (strnlen(value, 65) < 65) {
 145                         got_domain = 1;
 146                 } else {
 147                         printf("domain name too long\n");
 148                         return 1;
 149                 }
 150         } else if (strncmp(data, "uid", 3) == 0) {
 151                 if (value && *value) {
 152                         got_uid = 1;
 153                 }
 154         } else if (strncmp(data, "gid", 3) == 0) {
 155                 if (value && *value) {
 156                         got_gid = 1;
 157                 }
 158         } /* else if (strnicmp(data, "file_mode", 4) == 0) {
 159                 if (value && *value) {
 160                         vol->file_mode =
 161                                 simple_strtoul(value, &value, 0);
 162                 }
 163         } else if (strnicmp(data, "dir_mode", 3) == 0) {
 164                 if (value && *value) {
 165                         vol->dir_mode =
 166                                 simple_strtoul(value, &value, 0);
 167                 }
 168         } else if (strnicmp(data, "port", 4) == 0) {
 169                 if (value && *value) {
 170                         vol->port =
 171                                 simple_strtoul(value, &value, 0);
 172                 }
 173         } else if (strnicmp(data, "rsize", 5) == 0) {
 174                 if (value && *value) {
 175                         vol->rsize =
 176                                 simple_strtoul(value, &value, 0);
 177                 }
 178         } else if (strnicmp(data, "wsize", 5) == 0) {
 179                 if (value && *value) {
 180                         vol->wsize =
 181                                 simple_strtoul(value, &value, 0);
 182                 }
 183         } else if (strnicmp(data, "version", 3) == 0) {
 184                 
 185         } else if (strnicmp(data, "rw", 2) == 0) {
 186                 
 187         } else
 188                 printf("CIFS: Unknown mount option %s\n",data); */
 189         }
 190         return 0;
 191 }
 192 
 193 /* Note that caller frees the returned buffer if necessary */
 194 char * parse_server(char * unc_name)
     /* [<][>][^][v][top][bottom][index][help] */
 195 {
 196         int length = strnlen(unc_name,1024);
 197         char * share;
 198         char * ipaddress_string = NULL;
 199         struct hostent * host_entry;
 200         struct in_addr server_ipaddr;
 201         int rc,j;
 202         char temp[64];
 203 
 204         if(length > 1023) {
 205                 printf("mount error: UNC name too long");
 206                 return 0;
 207         }
 208         if (strncasecmp("cifs://",unc_name,7) == 0)
 209                 return parse_cifs_url(unc_name+7);
 210         if (strncasecmp("smb://",unc_name,6) == 0) {
 211                 return parse_cifs_url(unc_name+6);
 212         }
 213 
 214         if(length < 3) {
 215                 /* BB add code to find DFS root here */
 216                 printf("\nMounting the DFS root for domain not implemented yet");
 217                 return 0;
 218         } else {
 219                 /* BB add support for \\\\ not just // */
 220                 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
 221                         printf("mount error: improperly formatted UNC name.");
 222                         printf(" %s does not begin with \\\\ or //\n",unc_name);
 223                         return 0;
 224                 } else {
 225                         unc_name[0] = '\\';
 226                         unc_name[1] = '\\';
 227                         unc_name += 2;
 228                         if ((share = strchr(unc_name, '/')) || 
 229                                 (share = strchr(unc_name,'\\'))) {
 230                                 *share = 0;  /* temporarily terminate the string */
 231                                 share += 1;
 232                                 host_entry = gethostbyname(unc_name);
 233                                 *(share - 1) = '\\'; /* put the slash back */
 234 /*                              rc = getipnodebyname(unc_name, AF_INET, AT_ADDRCONFIG ,&rc);*/
 235                                 if(host_entry == NULL) {
 236                                         printf("mount error: could not find target server. TCP name %s not found ", unc_name);
 237                                         printf(" rc = %d\n",rc);
 238                                         return 0;
 239                                 }
 240                                 else {
 241                                         /* BB should we pass an alternate version of the share name as Unicode */
 242                                         /* BB what about ipv6? BB */
 243                                         /* BB add retries with alternate servers in list */
 244 
 245                                         memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
 246 
 247                                         ipaddress_string = inet_ntoa(server_ipaddr);                                                                                     
 248                                         if(ipaddress_string == NULL) {
 249                                                 printf("mount error: could not get valid ip address for target server\n");
 250                                                 return 0;
 251                                         }
 252                                         return ipaddress_string; 
 253                                 }
 254                         } else {
 255                                 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
 256                                 printf("Mounting the DFS root for a particular server not implemented yet\n");
 257                                 return 0;
 258                         }
 259                 }
 260         }
 261 }
 262 
 263 static struct option longopts[] = {
 264         { "all", 0, 0, 'a' },
 265         { "help", 0, 0, 'h' },
 266         { "read-only", 0, 0, 'r' },
 267         { "ro", 0, 0, 'r' },
 268         { "verbose", 0, 0, 'v' },
 269         { "version", 0, 0, 'V' },
 270         { "read-write", 0, 0, 'w' },
 271         { "rw", 0, 0, 'w' },
 272         { "options", 1, 0, 'o' },
 273         { "types", 1, 0, 't' },
 274         { "replace", 0, 0, 129 },
 275         { "after", 0, 0, 130 },
 276         { "before", 0, 0, 131 },
 277         { "over", 0, 0, 132 },
 278         { "move", 0, 0, 133 },
 279         { "rsize",1, 0, 136 },
 280         { "wsize",1, 0, 137 },
 281         { "uid", 1, 0, 138},
 282         { "gid", 1, 0, 139},
 283         { "uuid",1,0,'U' },
 284         { "user",1,0,140},
 285         { "username",1,0,140},
 286         { "dom",1,0,141},
 287         { "domain",1,0,141},
 288         { "password",1,0,142},
 289         { NULL, 0, 0, 0 }
 290 };
 291 
 292 int main(int argc, char ** argv)
     /* [<][>][^][v][top][bottom][index][help] */
 293 {
 294         int c;
 295         int flags = MS_MANDLOCK | MS_MGC_VAL;
 296         char * orgoptions = NULL;
 297         char * share_name = NULL;
 298         char * domain_name = NULL;
 299         char * ipaddr = NULL;
 300         char * uuid = NULL;
 301         char * mountpoint;
 302         char * options;
 303         int rc,i;
 304         int rsize = 0;
 305         int wsize = 0;
 306         int nomtab = 0;
 307         int uid = 0;
 308         int gid = 0;
 309         int optlen = 0;
 310         struct stat statbuf;
 311         struct utsname sysinfo;
 312         struct mntent mountent;
 313         FILE * pmntfile;
 314 
 315         /* setlocale(LC_ALL, "");
 316 #if defined(LOCALEDIR)
 317         bindtextdomain(PACKAGE, LOCALEDIR);
 318         textdomain(PACKAGE); */
 319 #endif
 320 
 321         if(argc && argv) {
 322                 thisprogram = argv[0];
 323         }
 324         if(thisprogram == NULL)
 325                 thisprogram = "mount.cifs";
 326 
 327         uname(&sysinfo);
 328         /* BB add workstation name and domain and pass down */
 329 /*#ifdef _GNU_SOURCE
 330         printf(" node: %s machine: %s\n", sysinfo.nodename,sysinfo.machine);
 331 #endif*/
 332         if(argc < 3)
 333                 mount_cifs_usage();
 334         share_name = argv[1];
 335         mountpoint = argv[2];
 336         /* add sharename in opts string as unc= parm */
 337 
 338         while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:",
 339                          longopts, NULL)) != -1) {
 340                 switch (c) {
 341 /*      case 'a':              
 342                 ++mount_all;
 343                 break;
 344         case 'f':              
 345                 ++fake;
 346                 break;
 347         case 'F':
 348                 ++optfork;
 349                 break; */
 350                 case 'h':        /* help */
 351                         mount_cifs_usage ();
 352                         break;
 353 /*      case 'i':
 354                 external_allowed = 0;
 355                 break;
 356         case 'l':
 357                 list_with_volumelabel = 1;
 358                 break;
 359         case 'L':
 360                 volumelabel = optarg;
 361                 break; */
 362         case 'n':
 363                 ++nomtab;
 364                 break;
 365         case 'o':
 366                 if (orgoptions) {
 367                         orgoptions = strcat(orgoptions, ",");
 368                         orgoptions = strcat(orgoptions,optarg);
 369                 } else
 370                         orgoptions = strdup(optarg);
 371                 break;
 372 
 373 /*      case 'O':
 374                 if (test_opts)
 375                         test_opts = xstrconcat3(test_opts, ",", optarg);
 376                 else
 377                         test_opts = xstrdup(optarg);
 378                 break;*/
 379                 case 'r':  /* mount readonly */
 380                         flags |= MS_RDONLY;;
 381                         break;
 382                 case 'U':
 383                         uuid = optarg;
 384                         break;
 385                 case 'v':
 386                         ++verboseflag;
 387                         break;
 388 /*      case 'V':          
 389                 printf ("mount: %s\n", version);
 390                 exit (0);*/
 391                 case 'w':
 392                         flags &= ~MS_RDONLY;;
 393                         break;
 394 /*      case 0:
 395                 break;
 396 
 397         case 128: 
 398                 mounttype = MS_BIND;
 399                 break;
 400         case 129: 
 401                 mounttype = MS_REPLACE;
 402                 break;
 403         case 130: 
 404                 mounttype = MS_AFTER;
 405                 break;
 406         case 131: 
 407                 mounttype = MS_BEFORE;
 408                 break;
 409         case 132: 
 410                 mounttype = MS_OVER;
 411                 break;
 412         case 133: 
 413                 mounttype = MS_MOVE;
 414                 break;
 415         case 135:
 416                 mounttype = (MS_BIND | MS_REC);
 417                 break; */
 418                 case 136:
 419                         rsize = atoi(optarg) ;
 420                         break;
 421                 case 137:
 422                         wsize = atoi(optarg);
 423                         break;
 424                 case 138:
 425                         uid = atoi(optarg);
 426                         break;
 427                 case 139:
 428                         gid = atoi(optarg);
 429                         break;
 430                 case 140:
 431                         got_user = 1;
 432                         user_name = optarg;
 433                         break;
 434                 case 141:
 435                         domain_name = optarg;
 436                         break;
 437                 case 142:
 438                         got_password = 1;
 439                          mountpassword = optarg;
 440                         break;
 441                 case '?':
 442                 default:
 443                         mount_cifs_usage ();
 444                 }
 445         }
 446 
 447         /* canonicalize the path in argv[1]? */
 448 
 449         if(stat (mountpoint, &statbuf)) {
 450                 printf("mount error: mount point %s does not exist\n",mountpoint);
 451                 return -1;
 452         }
 453         if (S_ISDIR(statbuf.st_mode) == 0) {
 454                 printf("mount error: mount point %s is not a directory\n",mountpoint);
 455                 return -1;
 456         }
 457 
 458         if(geteuid()) {
 459                 printf("mount error: permission denied, not superuser and cifs.mount not installed SUID\n"); 
 460                 return -1;
 461         }
 462 
 463         ipaddr = parse_server(share_name);
 464 /*      if(share_name == NULL)
 465                 return 1; */
 466         if (parse_options(strdup(orgoptions)))
 467                 return 1;
 468 
 469         if(got_user == 0)
 470                 user_name = getusername();
 471        
 472 /*      check username for user%password format */
 473 
 474         if(got_password == 0) {
 475                 if (getenv("PASSWD")) {
 476                         mountpassword = malloc(33);
 477                         if(mountpassword) {
 478                                 strncpy(mountpassword,getenv("PASSWD"),32);
 479                                 got_password = 1;
 480                         }
 481 /*              } else if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
 482                         get_password_file();
 483                         got_password = 1;*/ /* BB add missing function */
 484                 } else {
 485                         mountpassword = getpass("Password: "); /* BB obsolete */
 486                         got_password = 1;
 487                 }
 488         }
 489         /* FIXME launch daemon (handles dfs name resolution and credential change) 
 490            remember to clear parms and overwrite password field before launching */
 491         if(orgoptions) {
 492                 optlen = strlen(orgoptions);
 493         } else
 494                 optlen = 0;
 495         if(share_name)
 496                 optlen += strlen(share_name) + 4;
 497         if(user_name)
 498                 optlen += strlen(user_name) + 6;
 499         if(ipaddr)
 500                 optlen += strlen(ipaddr) + 4;
 501         if(mountpassword)
 502                 optlen += strlen(mountpassword) + 6;
 503         options = malloc(optlen + 10);
 504 
 505     options[0] = 0;
 506         strncat(options,"unc=",4);
 507         strcat(options,share_name);
 508         if(ipaddr) {
 509                 strncat(options,",ip=",4);
 510                 strcat(options,ipaddr);
 511         } 
 512         if(user_name) {
 513                 strncat(options,",user=",6);
 514                 strcat(options,user_name);
 515         } 
 516         if(mountpassword) {
 517                 strncat(options,",pass=",6);
 518                 strcat(options,mountpassword);
 519         }
 520         strncat(options,",ver=",5);
 521         strcat(options,MOUNT_CIFS_VERSION);
 522 
 523         if(orgoptions) {
 524                 strcat(options,",");
 525                 strcat(options,orgoptions);
 526         }
 527         /* printf("\noptions %s \n",options);*/
 528         if(mount(share_name, mountpoint, "cifs", flags, options)) {
 529         /* remember to kill daemon on error */
 530                 switch (errno) {
 531                 case 0:
 532                         printf("mount failed but no error number set\n");
 533                         return 0;
 534                 case ENODEV:
 535                         printf("mount error: cifs filesystem not supported by the system\n");
 536                         break;
 537                 default:
 538                         printf("mount error %d = %s",errno,strerror(errno));
 539                 }
 540                 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
 541                 return -1;
 542         } else {
 543                 pmntfile = setmntent(MOUNTED, "a+");
 544                 if(pmntfile) {
 545                         mountent.mnt_fsname = share_name;
 546                         mountent.mnt_dir = mountpoint; 
 547                         mountent.mnt_type = "cifs"; 
 548                         mountent.mnt_opts = "";
 549                         mountent.mnt_freq = 0;
 550                         mountent.mnt_passno = 0;
 551                         rc = addmntent(pmntfile,&mountent);
 552                         endmntent(pmntfile);
 553                 } else {
 554                     printf("could not update mount table\n");
 555                 }
 556         }
 557         return 0;
 558 }
 559 

/* [<][>][^][v][top][bottom][index][help] */