📄 mount.cifs.c
字号:
/* Mount helper utility for Linux CIFS VFS (virtual filesystem) client Copyright (C) 2003,2005 Steve French (sfrench@us.ibm.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <pwd.h>#include <grp.h>#include <ctype.h>#include <sys/types.h>#include <sys/mount.h>#include <sys/stat.h>#include <sys/utsname.h>#include <sys/socket.h>#include <arpa/inet.h>#include <getopt.h>#include <errno.h>#include <netdb.h>#include <string.h>#include <mntent.h>#include <fcntl.h>#define MOUNT_CIFS_VERSION_MAJOR "1"#define MOUNT_CIFS_VERSION_MINOR "10"#ifndef MOUNT_CIFS_VENDOR_SUFFIX#define MOUNT_CIFS_VENDOR_SUFFIX ""#endif#ifndef MS_MOVE #define MS_MOVE 8192 #endif char * thisprogram;int verboseflag = 0;static int got_password = 0;static int got_user = 0;static int got_domain = 0;static int got_ip = 0;static int got_unc = 0;static int got_uid = 0;static int got_gid = 0;static int free_share_name = 0;static char * user_name = NULL;static char * mountpassword = NULL;char * domain_name = NULL;/* BB finish BB cifs_umount open nofollow - avoid symlink exposure? get owner of dir see if matches self or if root call system(umount argv) etc. BB end finish BB */static char * check_for_domain(char **);static void mount_cifs_usage(void){ printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram); printf("\nMount the remote target, specified as a UNC name,"); printf(" to a local directory.\n\nOptions:\n"); printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n"); printf("\nLess commonly used options:"); printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,"); printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,"); printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>"); printf("\n\nOptions not needed for servers supporting CIFS Unix extensions"); printf("\n\t(e.g. unneeded for mounts to most Samba versions):"); printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu"); printf("\n\nRarely used options:"); printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,"); printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,"); printf("\n\tnointr,ignorecase,noposixpaths,noacl"); printf("\n\nOptions are described in more detail in the manual page"); printf("\n\tman 8 mount.cifs\n"); printf("\nTo display the version number of the mount helper:"); printf("\n\t%s -V\n",thisprogram); if(mountpassword) { memset(mountpassword,0,64); free(mountpassword); } exit(1);}/* caller frees username if necessary */static char * getusername(void) { char *username = NULL; struct passwd *password = getpwuid(getuid()); if (password) { username = password->pw_name; } return username;}static char * parse_cifs_url(char * unc_name){ printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name); return NULL;}static int open_cred_file(char * file_name){ char * line_buf; char * temp_val; FILE * fs; int i, length; fs = fopen(file_name,"r"); if(fs == NULL) return errno; line_buf = malloc(4096); if(line_buf == NULL) { fclose(fs); return -ENOMEM; } while(fgets(line_buf,4096,fs)) { /* parse line from credential file */ /* eat leading white space */ for(i=0;i<4086;i++) { if((line_buf[i] != ' ') && (line_buf[i] != '\t')) break; /* if whitespace - skip past it */ } if (strncasecmp("username",line_buf+i,8) == 0) { temp_val = strchr(line_buf + i,'='); if(temp_val) { /* go past equals sign */ temp_val++; for(length = 0;length<4087;length++) { if(temp_val[length] == '\n') break; } if(length > 4086) { printf("mount.cifs failed due to malformed username in credentials file"); memset(line_buf,0,4096); if(mountpassword) { memset(mountpassword,0,64); } exit(1); } else { got_user = 1; user_name = calloc(1 + length,1); /* BB adding free of user_name string before exit, not really necessary but would be cleaner */ strncpy(user_name,temp_val, length); } } } else if (strncasecmp("password",line_buf+i,8) == 0) { temp_val = strchr(line_buf+i,'='); if(temp_val) { /* go past equals sign */ temp_val++; for(length = 0;length<65;length++) { if(temp_val[length] == '\n') break; } if(length > 64) { printf("mount.cifs failed: password in credentials file too long\n"); memset(line_buf,0, 4096); if(mountpassword) { memset(mountpassword,0,64); } exit(1); } else { if(mountpassword == NULL) { mountpassword = calloc(65,1); } else memset(mountpassword,0,64); if(mountpassword) { strncpy(mountpassword,temp_val,length); got_password = 1; } } } } else if (strncasecmp("domain",line_buf+i,6) == 0) { temp_val = strchr(line_buf+i,'='); if(temp_val) { /* go past equals sign */ temp_val++; if(verboseflag) printf("\nDomain %s\n",temp_val); for(length = 0;length<65;length++) { if(temp_val[length] == '\n') break; } if(length > 64) { printf("mount.cifs failed: domain in credentials file too long\n"); if(mountpassword) { memset(mountpassword,0,64); } exit(1); } else { if(domain_name == NULL) { domain_name = calloc(65,1); } else memset(domain_name,0,64); if(domain_name) { strncpy(domain_name,temp_val,length); got_domain = 1; } } } } } fclose(fs); if(line_buf) { memset(line_buf,0,4096); free(line_buf); } return 0;}static int get_password_from_file(int file_descript, char * filename){ int rc = 0; int i; char c; if(mountpassword == NULL) mountpassword = calloc(65,1); else memset(mountpassword, 0, 64); if(filename != NULL) { file_descript = open(filename, O_RDONLY); if(file_descript < 0) { printf("mount.cifs failed. %s attempting to open password file %s\n", strerror(errno),filename); exit(1); } } /* else file already open and fd provided */ for(i=0;i<64;i++) { rc = read(file_descript,&c,1); if(rc < 0) { printf("mount.cifs failed. Error %s reading password file\n",strerror(errno)); memset(mountpassword,0,64); if(filename != NULL) close(file_descript); exit(1); } else if(rc == 0) { if(mountpassword[0] == 0) { if(verboseflag) printf("\nWarning: null password used since cifs password file empty"); } break; } else /* read valid character */ { if((c == 0) || (c == '\n')) { break; } else mountpassword[i] = c; } } if((i == 64) && (verboseflag)) { printf("\nWarning: password longer than 64 characters specified in cifs password file"); } got_password = 1; if(filename != NULL) { close(file_descript); } return rc;}static int parse_options(char ** optionsp, int * filesys_flags){ char * data; char * percent_char = NULL; char * value = NULL; char * next_keyword = NULL; char * out = NULL; int out_len = 0; int word_len; int rc = 0; if (!optionsp || !*optionsp) return 1; data = *optionsp; if(verboseflag) printf("parsing options: %s\n", data); /* BB fixme check for separator override BB *//* while ((data = strsep(&options, ",")) != NULL) { */ while(data != NULL) { /* check if ends with trailing comma */ if(*data == 0) break; /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */ /* data = next keyword */ /* value = next value ie stuff after equal sign */ next_keyword = strchr(data,','); /* BB handle sep= */ /* temporarily null terminate end of keyword=value pair */ if(next_keyword) *next_keyword++ = 0; /* temporarily null terminate keyword to make keyword and value distinct */ if ((value = strchr(data, '=')) != NULL) { *value = '\0'; value++; } if (strncmp(data, "users",5) == 0) { if(!value || !*value) { goto nocopy; } } else if (strncmp(data, "user_xattr",10) == 0) { /* do nothing - need to skip so not parsed as user name */ } else if (strncmp(data, "user", 4) == 0) { if (!value || !*value) { if(data[4] == '\0') { if(verboseflag) printf("\nskipping empty user mount parameter\n"); /* remove the parm since it would otherwise be confusing to the kernel code which would think it was a real username */ goto nocopy; } else { printf("username specified with no parameter\n"); return 1; /* needs_arg; */ } } else { if (strnlen(value, 260) < 260) { got_user=1; percent_char = strchr(value,'%'); if(percent_char) { *percent_char = ','; if(mountpassword == NULL) mountpassword = calloc(65,1); if(mountpassword) { if(got_password) printf("\nmount.cifs warning - password specified twice\n"); got_password = 1; percent_char++; strncpy(mountpassword, percent_char,64); /* remove password from username */ while(*percent_char != 0) { *percent_char = ','; percent_char++; } } } /* this is only case in which the user name buf is not malloc - so we have to check for domain name embedded within the user name here since the later call to check_for_domain will not be invoked */ domain_name = check_for_domain(&value); } else { printf("username too long\n"); return 1; } } } else if (strncmp(data, "pass", 4) == 0) { if (!value || !*value) { if(got_password) { printf("\npassword specified twice, ignoring second\n"); } else got_password = 1; } else if (strnlen(value, 17) < 17) { if(got_password) printf("\nmount.cifs warning - password specified twice\n"); got_password = 1; } else { printf("password too long\n"); return 1; } } else if (strncmp(data, "ip", 2) == 0) { if (!value || !*value) { printf("target ip address argument missing"); } else if (strnlen(value, 35) < 35) { if(verboseflag) printf("ip address %s override specified\n",value); got_ip = 1; } else { printf("ip address too long\n"); return 1; } } else if ((strncmp(data, "unc", 3) == 0) || (strncmp(data, "target", 6) == 0) || (strncmp(data, "path", 4) == 0)) { if (!value || !*value) { printf("invalid path to network resource\n"); return 1; /* needs_arg; */ } else if(strnlen(value,5) < 5) { printf("UNC name too short"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -