00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _GNU_SOURCE
00020 #define _GNU_SOURCE
00021 #endif
00022
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 #include <pwd.h>
00027 #include <grp.h>
00028 #include <ctype.h>
00029 #include <sys/types.h>
00030 #include <sys/mount.h>
00031 #include <sys/stat.h>
00032 #include <sys/utsname.h>
00033 #include <sys/socket.h>
00034 #include <arpa/inet.h>
00035 #include <getopt.h>
00036 #include <errno.h>
00037 #include <netdb.h>
00038 #include <string.h>
00039 #include <mntent.h>
00040 #include <fcntl.h>
00041 #include <limits.h>
00042
00043 #define MOUNT_CIFS_VERSION_MAJOR "1"
00044 #define MOUNT_CIFS_VERSION_MINOR "10"
00045
00046 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
00047 #ifdef _SAMBA_BUILD_
00048 #include "include/version.h"
00049 #ifdef SAMBA_VERSION_VENDOR_SUFFIX
00050 #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING"-"SAMBA_VERSION_VENDOR_SUFFIX
00051 #else
00052 #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING
00053 #endif
00054 #else
00055 #define MOUNT_CIFS_VENDOR_SUFFIX ""
00056 #endif
00057 #endif
00058
00059 #ifndef MS_MOVE
00060 #define MS_MOVE 8192
00061 #endif
00062
00063 #ifndef MS_BIND
00064 #define MS_BIND 4096
00065 #endif
00066
00067 #define MAX_UNC_LEN 1024
00068
00069 #define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
00070
00071 const char *thisprogram;
00072 int verboseflag = 0;
00073 static int got_password = 0;
00074 static int got_user = 0;
00075 static int got_domain = 0;
00076 static int got_ip = 0;
00077 static int got_unc = 0;
00078 static int got_uid = 0;
00079 static int got_gid = 0;
00080 static char * user_name = NULL;
00081 static char * mountpassword = NULL;
00082 char * domain_name = NULL;
00083 char * prefixpath = NULL;
00084
00085
00086
00087
00088
00089
00090 size_t strlcpy(char *d, const char *s, size_t bufsize)
00091 {
00092 size_t len = strlen(s);
00093 size_t ret = len;
00094 if (bufsize <= 0) return 0;
00095 if (len >= bufsize) len = bufsize-1;
00096 memcpy(d, s, len);
00097 d[len] = 0;
00098 return ret;
00099 }
00100
00101
00102
00103
00104 size_t strlcat(char *d, const char *s, size_t bufsize)
00105 {
00106 size_t len1 = strlen(d);
00107 size_t len2 = strlen(s);
00108 size_t ret = len1 + len2;
00109
00110 if (len1+len2 >= bufsize) {
00111 if (bufsize < (len1+1)) {
00112 return ret;
00113 }
00114 len2 = bufsize - (len1+1);
00115 }
00116 if (len2 > 0) {
00117 memcpy(d+len1, s, len2);
00118 d[len1+len2] = 0;
00119 }
00120 return ret;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 static char * check_for_domain(char **);
00133
00134
00135 static void mount_cifs_usage(void)
00136 {
00137 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram);
00138 printf("\nMount the remote target, specified as a UNC name,");
00139 printf(" to a local directory.\n\nOptions:\n");
00140 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
00141 printf("\nLess commonly used options:");
00142 printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
00143 printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
00144 printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
00145 printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
00146 printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
00147 printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
00148 printf("\n\nRarely used options:");
00149 printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
00150 printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
00151 printf("\n\tnointr,ignorecase,noposixpaths,noacl");
00152 printf("\n\nOptions are described in more detail in the manual page");
00153 printf("\n\tman 8 mount.cifs\n");
00154 printf("\nTo display the version number of the mount helper:");
00155 printf("\n\t%s -V\n",thisprogram);
00156
00157 if(mountpassword) {
00158 memset(mountpassword,0,64);
00159 free(mountpassword);
00160 mountpassword = NULL;
00161 }
00162 exit(1);
00163 }
00164
00165
00166 static char * getusername(void) {
00167 char *username = NULL;
00168 struct passwd *password = getpwuid(getuid());
00169
00170 if (password) {
00171 username = password->pw_name;
00172 }
00173 return username;
00174 }
00175
00176 static char * parse_cifs_url(char * unc_name)
00177 {
00178 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name);
00179 return NULL;
00180 }
00181
00182 static int open_cred_file(char * file_name)
00183 {
00184 char * line_buf;
00185 char * temp_val;
00186 FILE * fs;
00187 int i, length;
00188 fs = fopen(file_name,"r");
00189 if(fs == NULL)
00190 return errno;
00191 line_buf = (char *)malloc(4096);
00192 if(line_buf == NULL) {
00193 fclose(fs);
00194 return -ENOMEM;
00195 }
00196
00197 while(fgets(line_buf,4096,fs)) {
00198
00199
00200
00201 for(i=0;i<4086;i++) {
00202 if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
00203 break;
00204
00205 }
00206 if (strncasecmp("username",line_buf+i,8) == 0) {
00207 temp_val = strchr(line_buf + i,'=');
00208 if(temp_val) {
00209
00210 temp_val++;
00211 for(length = 0;length<4087;length++) {
00212 if ((temp_val[length] == '\n')
00213 || (temp_val[length] == '\0')) {
00214 break;
00215 }
00216 }
00217 if(length > 4086) {
00218 printf("mount.cifs failed due to malformed username in credentials file");
00219 memset(line_buf,0,4096);
00220 if(mountpassword) {
00221 memset(mountpassword,0,64);
00222 }
00223 exit(1);
00224 } else {
00225 got_user = 1;
00226 user_name = (char *)calloc(1 + length,1);
00227
00228
00229 strncpy(user_name,temp_val, length);
00230 }
00231 }
00232 } else if (strncasecmp("password",line_buf+i,8) == 0) {
00233 temp_val = strchr(line_buf+i,'=');
00234 if(temp_val) {
00235
00236 temp_val++;
00237 for(length = 0;length<65;length++) {
00238 if ((temp_val[length] == '\n')
00239 || (temp_val[length] == '\0')) {
00240 break;
00241 }
00242 }
00243 if(length > 64) {
00244 printf("mount.cifs failed: password in credentials file too long\n");
00245 memset(line_buf,0, 4096);
00246 if(mountpassword) {
00247 memset(mountpassword,0,64);
00248 }
00249 exit(1);
00250 } else {
00251 if(mountpassword == NULL) {
00252 mountpassword = (char *)calloc(65,1);
00253 } else
00254 memset(mountpassword,0,64);
00255 if(mountpassword) {
00256 strncpy(mountpassword,temp_val,length);
00257 got_password = 1;
00258 }
00259 }
00260 }
00261 } else if (strncasecmp("domain",line_buf+i,6) == 0) {
00262 temp_val = strchr(line_buf+i,'=');
00263 if(temp_val) {
00264
00265 temp_val++;
00266 if(verboseflag)
00267 printf("\nDomain %s\n",temp_val);
00268 for(length = 0;length<65;length++) {
00269 if ((temp_val[length] == '\n')
00270 || (temp_val[length] == '\0')) {
00271 break;
00272 }
00273 }
00274 if(length > 64) {
00275 printf("mount.cifs failed: domain in credentials file too long\n");
00276 if(mountpassword) {
00277 memset(mountpassword,0,64);
00278 }
00279 exit(1);
00280 } else {
00281 if(domain_name == NULL) {
00282 domain_name = (char *)calloc(65,1);
00283 } else
00284 memset(domain_name,0,64);
00285 if(domain_name) {
00286 strncpy(domain_name,temp_val,length);
00287 got_domain = 1;
00288 }
00289 }
00290 }
00291 }
00292
00293 }
00294 fclose(fs);
00295 if(line_buf) {
00296 memset(line_buf,0,4096);
00297 free(line_buf);
00298 line_buf = NULL;
00299 }
00300 return 0;
00301 }
00302
00303 static int get_password_from_file(int file_descript, char * filename)
00304 {
00305 int rc = 0;
00306 int i;
00307 char c;
00308
00309 if(mountpassword == NULL)
00310 mountpassword = (char *)calloc(65,1);
00311 else
00312 memset(mountpassword, 0, 64);
00313
00314 if (mountpassword == NULL) {
00315 printf("malloc failed\n");
00316 exit(1);
00317 }
00318
00319 if(filename != NULL) {
00320 file_descript = open(filename, O_RDONLY);
00321 if(file_descript < 0) {
00322 printf("mount.cifs failed. %s attempting to open password file %s\n",
00323 strerror(errno),filename);
00324 exit(1);
00325 }
00326 }
00327
00328
00329 for(i=0;i<64;i++) {
00330 rc = read(file_descript,&c,1);
00331 if(rc < 0) {
00332 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno));
00333 memset(mountpassword,0,64);
00334 if(filename != NULL)
00335 close(file_descript);
00336 exit(1);
00337 } else if(rc == 0) {
00338 if(mountpassword[0] == 0) {
00339 if(verboseflag)
00340 printf("\nWarning: null password used since cifs password file empty");
00341 }
00342 break;
00343 } else {
00344 if((c == 0) || (c == '\n')) {
00345 break;
00346 } else
00347 mountpassword[i] = c;
00348 }
00349 }
00350 if((i == 64) && (verboseflag)) {
00351 printf("\nWarning: password longer than 64 characters specified in cifs password file");
00352 }
00353 got_password = 1;
00354 if(filename != NULL) {
00355 close(file_descript);
00356 }
00357
00358 return rc;
00359 }
00360
00361 static int parse_options(char ** optionsp, int * filesys_flags)
00362 {
00363 const char * data;
00364 char * percent_char = NULL;
00365 char * value = NULL;
00366 char * next_keyword = NULL;
00367 char * out = NULL;
00368 int out_len = 0;
00369 int word_len;
00370 int rc = 0;
00371 char user[32];
00372 char group[32];
00373
00374 if (!optionsp || !*optionsp)
00375 return 1;
00376 data = *optionsp;
00377
00378 if(verboseflag)
00379 printf("parsing options: %s\n", data);
00380
00381
00382
00383 if (getuid()) {
00384 got_uid = 1;
00385 snprintf(user,sizeof(user),"%u",getuid());
00386 got_gid = 1;
00387 snprintf(group,sizeof(group),"%u",getgid());
00388 }
00389
00390
00391 while(data != NULL) {
00392
00393 if(*data == 0)
00394 break;
00395
00396
00397
00398
00399
00400 next_keyword = strchr(data,',');
00401
00402
00403 if(next_keyword)
00404 *next_keyword++ = 0;
00405
00406
00407 if ((value = strchr(data, '=')) != NULL) {
00408 *value = '\0';
00409 value++;
00410 }
00411
00412 if (strncmp(data, "users",5) == 0) {
00413 if(!value || !*value) {
00414 goto nocopy;
00415 }
00416 } else if (strncmp(data, "user_xattr",10) == 0) {
00417
00418 } else if (strncmp(data, "user", 4) == 0) {
00419
00420 if (!value || !*value) {
00421 if(data[4] == '\0') {
00422 if(verboseflag)
00423 printf("\nskipping empty user mount parameter\n");
00424
00425
00426 goto nocopy;
00427 } else {
00428 printf("username specified with no parameter\n");
00429 return 1;
00430 }
00431 } else {
00432 if (strnlen(value, 260) < 260) {
00433 got_user=1;
00434 percent_char = strchr(value,'%');
00435 if(percent_char) {
00436 *percent_char = ',';
00437 if(mountpassword == NULL)
00438 mountpassword = (char *)calloc(65,1);
00439 if(mountpassword) {
00440 if(got_password)
00441 printf("\nmount.cifs warning - password specified twice\n");
00442 got_password = 1;
00443 percent_char++;
00444 strncpy(mountpassword, percent_char,64);
00445
00446 while(*percent_char != 0) {
00447 *percent_char = ',';
00448 percent_char++;
00449 }
00450 }
00451 }
00452
00453
00454
00455
00456
00457
00458 domain_name = check_for_domain(&value);
00459 } else {
00460 printf("username too long\n");
00461 return 1;
00462 }
00463 }
00464 } else if (strncmp(data, "pass", 4) == 0) {
00465 if (!value || !*value) {
00466 if(got_password) {
00467 printf("\npassword specified twice, ignoring second\n");
00468 } else
00469 got_password = 1;
00470 } else if (strnlen(value, 17) < 17) {
00471 if(got_password)
00472 printf("\nmount.cifs warning - password specified twice\n");
00473 got_password = 1;
00474 } else {
00475 printf("password too long\n");
00476 return 1;
00477 }
00478 } else if (strncmp(data, "sec", 3) == 0) {
00479 if (value) {
00480 if (!strncmp(value, "none", 4) ||
00481 !strncmp(value, "krb5", 4))
00482 got_password = 1;
00483 }
00484 } else if (strncmp(data, "ip", 2) == 0) {
00485 if (!value || !*value) {
00486 printf("target ip address argument missing");
00487 } else if (strnlen(value, 35) < 35) {
00488 if(verboseflag)
00489 printf("ip address %s override specified\n",value);
00490 got_ip = 1;
00491 } else {
00492 printf("ip address too long\n");
00493 return 1;
00494 }
00495 } else if ((strncmp(data, "unc", 3) == 0)
00496 || (strncmp(data, "target", 6) == 0)
00497 || (strncmp(data, "path", 4) == 0)) {
00498 if (!value || !*value) {
00499 printf("invalid path to network resource\n");
00500 return 1;
00501 } else if(strnlen(value,5) < 5) {
00502 printf("UNC name too short");
00503 }
00504
00505 if (strnlen(value, 300) < 300) {
00506 got_unc = 1;
00507 if (strncmp(value, "//", 2) == 0) {
00508 if(got_unc)
00509 printf("unc name specified twice, ignoring second\n");
00510 else
00511 got_unc = 1;
00512 } else if (strncmp(value, "\\\\", 2) != 0) {
00513 printf("UNC Path does not begin with // or \\\\ \n");
00514 return 1;
00515 } else {
00516 if(got_unc)
00517 printf("unc name specified twice, ignoring second\n");
00518 else
00519 got_unc = 1;
00520 }
00521 } else {
00522 printf("CIFS: UNC name too long\n");
00523 return 1;
00524 }
00525 } else if ((strncmp(data, "domain", 3) == 0)
00526 || (strncmp(data, "workgroup", 5) == 0)) {
00527 if (!value || !*value) {
00528 printf("CIFS: invalid domain name\n");
00529 return 1;
00530 }
00531 if (strnlen(value, 65) < 65) {
00532 got_domain = 1;
00533 } else {
00534 printf("domain name too long\n");
00535 return 1;
00536 }
00537 } else if (strncmp(data, "cred", 4) == 0) {
00538 if (value && *value) {
00539 rc = open_cred_file(value);
00540 if(rc) {
00541 printf("error %d opening credential file %s\n",rc, value);
00542 return 1;
00543 }
00544 } else {
00545 printf("invalid credential file name specified\n");
00546 return 1;
00547 }
00548 } else if (strncmp(data, "uid", 3) == 0) {
00549 if (value && *value) {
00550 got_uid = 1;
00551 if (!isdigit(*value)) {
00552 struct passwd *pw;
00553
00554 if (!(pw = getpwnam(value))) {
00555 printf("bad user name \"%s\"\n", value);
00556 exit(1);
00557 }
00558 snprintf(user, sizeof(user), "%u", pw->pw_uid);
00559 } else {
00560 strlcpy(user,value,sizeof(user));
00561 }
00562 }
00563 goto nocopy;
00564 } else if (strncmp(data, "gid", 3) == 0) {
00565 if (value && *value) {
00566 got_gid = 1;
00567 if (!isdigit(*value)) {
00568 struct group *gr;
00569
00570 if (!(gr = getgrnam(value))) {
00571 printf("bad group name \"%s\"\n", value);
00572 exit(1);
00573 }
00574 snprintf(group, sizeof(group), "%u", gr->gr_gid);
00575 } else {
00576 strlcpy(group,value,sizeof(group));
00577 }
00578 }
00579 goto nocopy;
00580
00581 } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
00582 if (!value || !*value) {
00583 printf ("Option '%s' requires a numerical argument\n", data);
00584 return 1;
00585 }
00586
00587 if (value[0] != '0') {
00588 printf ("WARNING: '%s' not expressed in octal.\n", data);
00589 }
00590
00591 if (strcmp (data, "fmask") == 0) {
00592 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
00593 data = "file_mode";
00594 }
00595 } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
00596 if (!value || !*value) {
00597 printf ("Option '%s' requires a numerical argument\n", data);
00598 return 1;
00599 }
00600
00601 if (value[0] != '0') {
00602 printf ("WARNING: '%s' not expressed in octal.\n", data);
00603 }
00604
00605 if (strcmp (data, "dmask") == 0) {
00606 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
00607 data = "dir_mode";
00608 }
00609
00610
00611
00612
00613
00614
00615 } else if (strncmp(data, "nosuid", 6) == 0) {
00616 *filesys_flags |= MS_NOSUID;
00617 } else if (strncmp(data, "suid", 4) == 0) {
00618 *filesys_flags &= ~MS_NOSUID;
00619 } else if (strncmp(data, "nodev", 5) == 0) {
00620 *filesys_flags |= MS_NODEV;
00621 } else if ((strncmp(data, "nobrl", 5) == 0) ||
00622 (strncmp(data, "nolock", 6) == 0)) {
00623 *filesys_flags &= ~MS_MANDLOCK;
00624 } else if (strncmp(data, "dev", 3) == 0) {
00625 *filesys_flags &= ~MS_NODEV;
00626 } else if (strncmp(data, "noexec", 6) == 0) {
00627 *filesys_flags |= MS_NOEXEC;
00628 } else if (strncmp(data, "exec", 4) == 0) {
00629 *filesys_flags &= ~MS_NOEXEC;
00630 } else if (strncmp(data, "guest", 5) == 0) {
00631 got_password=1;
00632 } else if (strncmp(data, "ro", 2) == 0) {
00633 *filesys_flags |= MS_RDONLY;
00634 } else if (strncmp(data, "rw", 2) == 0) {
00635 *filesys_flags &= ~MS_RDONLY;
00636 } else if (strncmp(data, "remount", 7) == 0) {
00637 *filesys_flags |= MS_REMOUNT;
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 word_len = strlen(data);
00661 if (value)
00662 word_len += 1 + strlen(value);
00663
00664 out = (char *)realloc(out, out_len + word_len + 2);
00665 if (out == NULL) {
00666 perror("malloc");
00667 exit(1);
00668 }
00669
00670 if (out_len) {
00671 strlcat(out, ",", out_len + word_len + 2);
00672 out_len++;
00673 }
00674
00675 if (value)
00676 snprintf(out + out_len, word_len + 1, "%s=%s", data, value);
00677 else
00678 snprintf(out + out_len, word_len + 1, "%s", data);
00679 out_len = strlen(out);
00680
00681 nocopy:
00682 data = next_keyword;
00683 }
00684
00685
00686 if (got_uid) {
00687 word_len = strlen(user);
00688
00689 out = (char *)realloc(out, out_len + word_len + 6);
00690 if (out == NULL) {
00691 perror("malloc");
00692 exit(1);
00693 }
00694
00695 if (out_len) {
00696 strlcat(out, ",", out_len + word_len + 6);
00697 out_len++;
00698 }
00699 snprintf(out + out_len, word_len + 5, "uid=%s", user);
00700 out_len = strlen(out);
00701 }
00702 if (got_gid) {
00703 word_len = strlen(group);
00704
00705 out = (char *)realloc(out, out_len + 1 + word_len + 6);
00706 if (out == NULL) {
00707 perror("malloc");
00708 exit(1);
00709 }
00710
00711 if (out_len) {
00712 strlcat(out, ",", out_len + word_len + 6);
00713 out_len++;
00714 }
00715 snprintf(out + out_len, word_len + 5, "gid=%s", group);
00716 out_len = strlen(out);
00717 }
00718
00719 free(*optionsp);
00720 *optionsp = out;
00721 return 0;
00722 }
00723
00724
00725 static void check_for_comma(char ** ppasswrd)
00726 {
00727 char *new_pass_buf;
00728 char *pass;
00729 int i,j;
00730 int number_of_commas = 0;
00731 int len;
00732
00733 if(ppasswrd == NULL)
00734 return;
00735 else
00736 (pass = *ppasswrd);
00737
00738 len = strlen(pass);
00739
00740 for(i=0;i<len;i++) {
00741 if(pass[i] == ',')
00742 number_of_commas++;
00743 }
00744
00745 if(number_of_commas == 0)
00746 return;
00747 if(number_of_commas > 64) {
00748
00749 printf("\nInvalid password. Password contains too many commas.\n");
00750 return;
00751 }
00752
00753 new_pass_buf = (char *)malloc(len+number_of_commas+1);
00754 if(new_pass_buf == NULL)
00755 return;
00756
00757 for(i=0,j=0;i<len;i++,j++) {
00758 new_pass_buf[j] = pass[i];
00759 if(pass[i] == ',') {
00760 j++;
00761 new_pass_buf[j] = pass[i];
00762 }
00763 }
00764 new_pass_buf[len+number_of_commas] = 0;
00765
00766 free(*ppasswrd);
00767 *ppasswrd = new_pass_buf;
00768
00769 return;
00770 }
00771
00772
00773
00774
00775
00776 static char * check_for_domain(char **ppuser)
00777 {
00778 char * original_string;
00779 char * usernm;
00780 char * domainnm;
00781 int original_len;
00782 int len;
00783 int i;
00784
00785 if(ppuser == NULL)
00786 return NULL;
00787
00788 original_string = *ppuser;
00789
00790 if (original_string == NULL)
00791 return NULL;
00792
00793 original_len = strlen(original_string);
00794
00795 usernm = strchr(*ppuser,'/');
00796 if (usernm == NULL) {
00797 usernm = strchr(*ppuser,'\\');
00798 if (usernm == NULL)
00799 return NULL;
00800 }
00801
00802 if(got_domain) {
00803 printf("Domain name specified twice. Username probably malformed\n");
00804 return NULL;
00805 }
00806
00807 usernm[0] = 0;
00808 domainnm = *ppuser;
00809 if (domainnm[0] != 0) {
00810 got_domain = 1;
00811 } else {
00812 printf("null domain\n");
00813 }
00814 len = strlen(domainnm);
00815
00816
00817 domainnm = (char *)malloc(len+1);
00818 if(domainnm == NULL)
00819 return NULL;
00820
00821 strlcpy(domainnm,*ppuser,len+1);
00822
00823
00824 len = strlen(usernm+1);
00825
00826 if(len >= original_len) {
00827
00828 return domainnm;
00829 }
00830
00831 for(i=0;i<original_len;i++) {
00832 if(i<len)
00833 original_string[i] = usernm[i+1];
00834 else
00835 original_string[i] = ',';
00836 }
00837
00838
00839
00840
00841
00842
00843 return domainnm;
00844 }
00845
00846
00847 static void replace_char(char *string, char from, char to, int maxlen)
00848 {
00849 char *lastchar = string + maxlen;
00850 while (string) {
00851 string = strchr(string, from);
00852 if (string) {
00853 *string = to;
00854 if (string >= lastchar)
00855 return;
00856 }
00857 }
00858 }
00859
00860
00861 static char * parse_server(char ** punc_name)
00862 {
00863 char * unc_name = *punc_name;
00864 int length = strnlen(unc_name, MAX_UNC_LEN);
00865 char * share;
00866 char * ipaddress_string = NULL;
00867 struct hostent * host_entry = NULL;
00868 struct in_addr server_ipaddr;
00869
00870 if(length > (MAX_UNC_LEN - 1)) {
00871 printf("mount error: UNC name too long");
00872 return NULL;
00873 }
00874 if (strncasecmp("cifs://",unc_name,7) == 0)
00875 return parse_cifs_url(unc_name+7);
00876 if (strncasecmp("smb://",unc_name,6) == 0) {
00877 return parse_cifs_url(unc_name+6);
00878 }
00879
00880 if(length < 3) {
00881
00882 printf("\nMounting the DFS root for domain not implemented yet\n");
00883 return NULL;
00884 } else {
00885 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
00886
00887 share = strchr(unc_name,':');
00888 if(share) {
00889 *punc_name = (char *)malloc(length+3);
00890 if(*punc_name == NULL) {
00891
00892
00893 *punc_name = unc_name;
00894 return NULL;
00895 }
00896 *share = '/';
00897 strncpy((*punc_name)+2,unc_name,length);
00898 free(unc_name);
00899 unc_name = *punc_name;
00900 unc_name[length+2] = 0;
00901 goto continue_unc_parsing;
00902 } else {
00903 printf("mount error: improperly formatted UNC name.");
00904 printf(" %s does not begin with \\\\ or //\n",unc_name);
00905 return NULL;
00906 }
00907 } else {
00908 continue_unc_parsing:
00909 unc_name[0] = '/';
00910 unc_name[1] = '/';
00911 unc_name += 2;
00912
00913
00914 if ((share = strpbrk(unc_name, "/\\"))) {
00915 *share = 0;
00916 share += 1;
00917 if(got_ip == 0) {
00918 host_entry = gethostbyname(unc_name);
00919 }
00920 *(share - 1) = '/';
00921
00922
00923 if ((prefixpath = strpbrk(share, "/\\"))) {
00924 *prefixpath = 0;
00925 if (!strlen(++prefixpath))
00926 prefixpath = NULL;
00927 }
00928 if(got_ip) {
00929 if(verboseflag)
00930 printf("ip address specified explicitly\n");
00931 return NULL;
00932 }
00933 if(host_entry == NULL) {
00934 printf("mount error: could not find target server. TCP name %s not found\n", unc_name);
00935 return NULL;
00936 } else {
00937
00938
00939
00940
00941 memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
00942
00943 ipaddress_string = inet_ntoa(server_ipaddr);
00944 if(ipaddress_string == NULL) {
00945 printf("mount error: could not get valid ip address for target server\n");
00946 return NULL;
00947 }
00948 return ipaddress_string;
00949 }
00950 } else {
00951
00952 printf("Mounting the DFS root for a particular server not implemented yet\n");
00953 return NULL;
00954 }
00955 }
00956 }
00957 }
00958
00959 static struct option longopts[] = {
00960 { "all", 0, NULL, 'a' },
00961 { "help",0, NULL, 'h' },
00962 { "move",0, NULL, 'm' },
00963 { "bind",0, NULL, 'b' },
00964 { "read-only", 0, NULL, 'r' },
00965 { "ro", 0, NULL, 'r' },
00966 { "verbose", 0, NULL, 'v' },
00967 { "version", 0, NULL, 'V' },
00968 { "read-write", 0, NULL, 'w' },
00969 { "rw", 0, NULL, 'w' },
00970 { "options", 1, NULL, 'o' },
00971 { "type", 1, NULL, 't' },
00972 { "rsize",1, NULL, 'R' },
00973 { "wsize",1, NULL, 'W' },
00974 { "uid", 1, NULL, '1'},
00975 { "gid", 1, NULL, '2'},
00976 { "user",1,NULL,'u'},
00977 { "username",1,NULL,'u'},
00978 { "dom",1,NULL,'d'},
00979 { "domain",1,NULL,'d'},
00980 { "password",1,NULL,'p'},
00981 { "pass",1,NULL,'p'},
00982 { "credentials",1,NULL,'c'},
00983 { "port",1,NULL,'P'},
00984
00985 { NULL, 0, NULL, 0 }
00986 };
00987
00988
00989
00990 static int
00991 uppercase_string(char *string)
00992 {
00993 if (!string)
00994 return 0;
00995
00996 while (*string) {
00997
00998 if ((unsigned char) string[0] & 0x80)
00999 return 0;
01000 *string = toupper((unsigned char) *string);
01001 string++;
01002 }
01003
01004 return 1;
01005 }
01006
01007 int main(int argc, char ** argv)
01008 {
01009 int c;
01010 int flags = MS_MANDLOCK;
01011 char * orgoptions = NULL;
01012 char * share_name = NULL;
01013 char * ipaddr = NULL;
01014 char * uuid = NULL;
01015 char * mountpoint = NULL;
01016 char * options = NULL;
01017 char * resolved_path = NULL;
01018 char * temp;
01019 char * dev_name;
01020 int rc;
01021 int rsize = 0;
01022 int wsize = 0;
01023 int nomtab = 0;
01024 int uid = 0;
01025 int gid = 0;
01026 int optlen = 0;
01027 int orgoptlen = 0;
01028 size_t options_size = 0;
01029 int retry = 0;
01030 struct stat statbuf;
01031 struct utsname sysinfo;
01032 struct mntent mountent;
01033 FILE * pmntfile;
01034
01035
01036
01037
01038
01039 if(argc && argv) {
01040 thisprogram = argv[0];
01041 } else {
01042 mount_cifs_usage();
01043 exit(1);
01044 }
01045
01046 if(thisprogram == NULL)
01047 thisprogram = "mount.cifs";
01048
01049 uname(&sysinfo);
01050
01051
01052
01053
01054
01055 if(argc > 2) {
01056 dev_name = argv[1];
01057 share_name = strndup(argv[1], MAX_UNC_LEN);
01058 if (share_name == NULL) {
01059 fprintf(stderr, "%s: %s", argv[0], strerror(ENOMEM));
01060 exit(1);
01061 }
01062 mountpoint = argv[2];
01063 } else {
01064 mount_cifs_usage();
01065 exit(1);
01066 }
01067
01068
01069
01070 while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:",
01071 longopts, NULL)) != -1) {
01072 switch (c) {
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 case '?':
01085 case 'h':
01086 mount_cifs_usage ();
01087 exit(1);
01088 case 'n':
01089 ++nomtab;
01090 break;
01091 case 'b':
01092 #ifdef MS_BIND
01093 flags |= MS_BIND;
01094 #else
01095 fprintf(stderr,
01096 "option 'b' (MS_BIND) not supported\n");
01097 #endif
01098 break;
01099 case 'm':
01100 #ifdef MS_MOVE
01101 flags |= MS_MOVE;
01102 #else
01103 fprintf(stderr,
01104 "option 'm' (MS_MOVE) not supported\n");
01105 #endif
01106 break;
01107 case 'o':
01108 orgoptions = strdup(optarg);
01109 break;
01110 case 'r':
01111 flags |= MS_RDONLY;
01112 break;
01113 case 'U':
01114 uuid = optarg;
01115 break;
01116 case 'v':
01117 ++verboseflag;
01118 break;
01119 case 'V':
01120 printf ("mount.cifs version: %s.%s%s\n",
01121 MOUNT_CIFS_VERSION_MAJOR,
01122 MOUNT_CIFS_VERSION_MINOR,
01123 MOUNT_CIFS_VENDOR_SUFFIX);
01124 if(mountpassword) {
01125 memset(mountpassword,0,64);
01126 }
01127 exit (0);
01128 case 'w':
01129 flags &= ~MS_RDONLY;
01130 break;
01131 case 'R':
01132 rsize = atoi(optarg) ;
01133 break;
01134 case 'W':
01135 wsize = atoi(optarg);
01136 break;
01137 case '1':
01138 if (isdigit(*optarg)) {
01139 char *ep;
01140
01141 uid = strtoul(optarg, &ep, 10);
01142 if (*ep) {
01143 printf("bad uid value \"%s\"\n", optarg);
01144 exit(1);
01145 }
01146 } else {
01147 struct passwd *pw;
01148
01149 if (!(pw = getpwnam(optarg))) {
01150 printf("bad user name \"%s\"\n", optarg);
01151 exit(1);
01152 }
01153 uid = pw->pw_uid;
01154 endpwent();
01155 }
01156 break;
01157 case '2':
01158 if (isdigit(*optarg)) {
01159 char *ep;
01160
01161 gid = strtoul(optarg, &ep, 10);
01162 if (*ep) {
01163 printf("bad gid value \"%s\"\n", optarg);
01164 exit(1);
01165 }
01166 } else {
01167 struct group *gr;
01168
01169 if (!(gr = getgrnam(optarg))) {
01170 printf("bad user name \"%s\"\n", optarg);
01171 exit(1);
01172 }
01173 gid = gr->gr_gid;
01174 endpwent();
01175 }
01176 break;
01177 case 'u':
01178 got_user = 1;
01179 user_name = optarg;
01180 break;
01181 case 'd':
01182 domain_name = optarg;
01183 got_domain = 1;
01184 break;
01185 case 'p':
01186 if(mountpassword == NULL)
01187 mountpassword = (char *)calloc(65,1);
01188 if(mountpassword) {
01189 got_password = 1;
01190 strncpy(mountpassword,optarg,64);
01191 }
01192 break;
01193 case 'S':
01194 get_password_from_file(0 ,NULL);
01195 break;
01196 case 't':
01197 break;
01198 default:
01199 printf("unknown mount option %c\n",c);
01200 mount_cifs_usage();
01201 exit(1);
01202 }
01203 }
01204
01205 if((argc < 3) || (dev_name == NULL) || (mountpoint == NULL)) {
01206 mount_cifs_usage();
01207 exit(1);
01208 }
01209
01210 if (getenv("PASSWD")) {
01211 if(mountpassword == NULL)
01212 mountpassword = (char *)calloc(65,1);
01213 if(mountpassword) {
01214 strncpy(mountpassword,getenv("PASSWD"),64);
01215 got_password = 1;
01216 }
01217 } else if (getenv("PASSWD_FD")) {
01218 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
01219 } else if (getenv("PASSWD_FILE")) {
01220 get_password_from_file(0, getenv("PASSWD_FILE"));
01221 }
01222
01223 if (orgoptions && parse_options(&orgoptions, &flags)) {
01224 rc = -1;
01225 goto mount_exit;
01226 }
01227 ipaddr = parse_server(&share_name);
01228 if((ipaddr == NULL) && (got_ip == 0)) {
01229 printf("No ip address specified and hostname not found\n");
01230 rc = -1;
01231 goto mount_exit;
01232 }
01233
01234
01235 resolved_path = (char *)malloc(PATH_MAX+1);
01236 if(resolved_path) {
01237
01238
01239 if (realpath(mountpoint, resolved_path)) {
01240 mountpoint = resolved_path;
01241 }
01242 }
01243 if(chdir(mountpoint)) {
01244 printf("mount error: can not change directory into mount target %s\n",mountpoint);
01245 rc = -1;
01246 goto mount_exit;
01247 }
01248
01249 if(stat (".", &statbuf)) {
01250 printf("mount error: mount point %s does not exist\n",mountpoint);
01251 rc = -1;
01252 goto mount_exit;
01253 }
01254
01255 if (S_ISDIR(statbuf.st_mode) == 0) {
01256 printf("mount error: mount point %s is not a directory\n",mountpoint);
01257 rc = -1;
01258 goto mount_exit;
01259 }
01260
01261 if((getuid() != 0) && (geteuid() == 0)) {
01262 if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
01263 #ifndef CIFS_ALLOW_USR_SUID
01264
01265
01266 flags |= MS_NOSUID | MS_NODEV;
01267 #endif
01268 } else {
01269 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
01270 return -1;
01271 }
01272 }
01273
01274 if(got_user == 0) {
01275 user_name = getusername();
01276 got_user = 1;
01277 }
01278
01279 if(got_password == 0) {
01280 char *tmp_pass;
01281 tmp_pass = getpass("Password: ");
01282
01283 mountpassword = (char *)calloc(65,1);
01284 if (!tmp_pass || !mountpassword) {
01285 printf("Password not entered, exiting.\n");
01286 return -1;
01287 }
01288 strncpy(mountpassword, tmp_pass, 64);
01289
01290 got_password = 1;
01291 }
01292
01293
01294 mount_retry:
01295 if(orgoptions) {
01296 optlen = strlen(orgoptions);
01297 orgoptlen = optlen;
01298 } else
01299 optlen = 0;
01300 if(share_name)
01301 optlen += strlen(share_name) + 4;
01302 else {
01303 printf("No server share name specified\n");
01304 printf("\nMounting the DFS root for server not implemented yet\n");
01305 exit(1);
01306 }
01307 if(user_name)
01308 optlen += strlen(user_name) + 6;
01309 if(ipaddr)
01310 optlen += strlen(ipaddr) + 4;
01311 if(mountpassword)
01312 optlen += strlen(mountpassword) + 6;
01313 if(options) {
01314 free(options);
01315 options = NULL;
01316 }
01317 options_size = optlen + 10 + 64;
01318 options = (char *)malloc(options_size + 8 );
01319
01320 if(options == NULL) {
01321 printf("Could not allocate memory for mount options\n");
01322 return -1;
01323 }
01324
01325 options[0] = 0;
01326 strlcpy(options,"unc=",options_size);
01327 strlcat(options,share_name,options_size);
01328
01329 temp = strrchr(options, '/');
01330 if(temp > options + 6)
01331 *temp = '\\';
01332 if(ipaddr) {
01333 strlcat(options,",ip=",options_size);
01334 strlcat(options,ipaddr,options_size);
01335 }
01336
01337 if(user_name) {
01338
01339 if(got_domain == 0)
01340 domain_name = check_for_domain(&user_name);
01341 strlcat(options,",user=",options_size);
01342 strlcat(options,user_name,options_size);
01343 }
01344 if(retry == 0) {
01345 if(domain_name) {
01346
01347 strlcat(options,",domain=",options_size);
01348 strlcat(options,domain_name,options_size);
01349 }
01350 }
01351 if(mountpassword) {
01352
01353
01354
01355 if(retry == 0)
01356 check_for_comma(&mountpassword);
01357 strlcat(options,",pass=",options_size);
01358 strlcat(options,mountpassword,options_size);
01359 }
01360
01361 strlcat(options,",ver=",options_size);
01362 strlcat(options,MOUNT_CIFS_VERSION_MAJOR,options_size);
01363
01364 if(orgoptions) {
01365 strlcat(options,",",options_size);
01366 strlcat(options,orgoptions,options_size);
01367 }
01368 if(prefixpath) {
01369 strlcat(options,",prefixpath=",options_size);
01370 strlcat(options,prefixpath,options_size);
01371 }
01372 if(verboseflag)
01373 printf("\nmount.cifs kernel mount options %s \n",options);
01374
01375
01376 replace_char(dev_name, '\\', '/', strlen(share_name));
01377
01378 if(mount(dev_name, mountpoint, "cifs", flags, options)) {
01379
01380 switch (errno) {
01381 case 0:
01382 printf("mount failed but no error number set\n");
01383 break;
01384 case ENODEV:
01385 printf("mount error: cifs filesystem not supported by the system\n");
01386 break;
01387 case ENXIO:
01388 if(retry == 0) {
01389 retry = 1;
01390 if (uppercase_string(dev_name) &&
01391 uppercase_string(share_name) &&
01392 uppercase_string(prefixpath)) {
01393 printf("retrying with upper case share name\n");
01394 goto mount_retry;
01395 }
01396 }
01397 default:
01398 printf("mount error %d = %s\n",errno,strerror(errno));
01399 }
01400 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
01401 rc = -1;
01402 goto mount_exit;
01403 } else {
01404 pmntfile = setmntent(MOUNTED, "a+");
01405 if(pmntfile) {
01406 mountent.mnt_fsname = dev_name;
01407 mountent.mnt_dir = mountpoint;
01408 mountent.mnt_type = CONST_DISCARD(char *,"cifs");
01409 mountent.mnt_opts = (char *)malloc(220);
01410 if(mountent.mnt_opts) {
01411 char * mount_user = getusername();
01412 memset(mountent.mnt_opts,0,200);
01413 if(flags & MS_RDONLY)
01414 strlcat(mountent.mnt_opts,"ro",220);
01415 else
01416 strlcat(mountent.mnt_opts,"rw",220);
01417 if(flags & MS_MANDLOCK)
01418 strlcat(mountent.mnt_opts,",mand",220);
01419 if(flags & MS_NOEXEC)
01420 strlcat(mountent.mnt_opts,",noexec",220);
01421 if(flags & MS_NOSUID)
01422 strlcat(mountent.mnt_opts,",nosuid",220);
01423 if(flags & MS_NODEV)
01424 strlcat(mountent.mnt_opts,",nodev",220);
01425 if(flags & MS_SYNCHRONOUS)
01426 strlcat(mountent.mnt_opts,",synch",220);
01427 if(mount_user) {
01428 if(getuid() != 0) {
01429 strlcat(mountent.mnt_opts,",user=",220);
01430 strlcat(mountent.mnt_opts,mount_user,220);
01431 }
01432
01433 }
01434 }
01435 mountent.mnt_freq = 0;
01436 mountent.mnt_passno = 0;
01437 rc = addmntent(pmntfile,&mountent);
01438 endmntent(pmntfile);
01439 if(mountent.mnt_opts) {
01440 free(mountent.mnt_opts);
01441 mountent.mnt_opts = NULL;
01442 }
01443 } else {
01444 printf("could not update mount table\n");
01445 }
01446 }
01447 rc = 0;
01448 mount_exit:
01449 if(mountpassword) {
01450 int len = strlen(mountpassword);
01451 memset(mountpassword,0,len);
01452 free(mountpassword);
01453 mountpassword = NULL;
01454 }
01455
01456 if(options) {
01457 memset(options,0,optlen);
01458 free(options);
01459 options = NULL;
01460 }
01461
01462 if(orgoptions) {
01463 memset(orgoptions,0,orgoptlen);
01464 free(orgoptions);
01465 orgoptions = NULL;
01466 }
01467 if(resolved_path) {
01468 free(resolved_path);
01469 resolved_path = NULL;
01470 }
01471
01472 free(share_name);
01473 return rc;
01474 }