diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-04-01 15:19:16 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@redhat.com> | 2010-04-01 15:19:16 -0400 |
commit | c610039ef674770ec92ff36d1f3c7a494bc3962c (patch) | |
tree | c032ca0e9f9cf585519537fe438ddc896b46214c /mount.cifs.c | |
parent | 0f4753b828e71b437924b48d168308884928fa6f (diff) | |
download | cifs-utils-c610039ef674770ec92ff36d1f3c7a494bc3962c.tar.gz cifs-utils-c610039ef674770ec92ff36d1f3c7a494bc3962c.tar.bz2 cifs-utils-c610039ef674770ec92ff36d1f3c7a494bc3962c.zip |
mount.cifs: add username and domain fields to parsed_mount_info
...and fill and use them accordingly.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'mount.cifs.c')
-rw-r--r-- | mount.cifs.c | 288 |
1 files changed, 116 insertions, 172 deletions
diff --git a/mount.cifs.c b/mount.cifs.c index 86edae8..26621ff 100644 --- a/mount.cifs.c +++ b/mount.cifs.c @@ -67,6 +67,9 @@ */ #define MAX_SHARE_LEN 256 +/* max length of username (somewhat made up here) */ +#define MAX_USERNAME_SIZE 32 + /* currently maximum length of IPv6 address string */ #define MAX_ADDRESS_LEN INET6_ADDRSTRLEN @@ -125,22 +128,22 @@ struct parsed_mount_info { char share[MAX_SHARE_LEN]; char prefix[PATH_MAX]; char options[MAX_OPTIONS_LEN]; + char domain[DOMAIN_SIZE + 1]; + char username[MAX_USERNAME_SIZE + 1]; char password[MOUNT_PASSWD_SIZE + 1]; char address_list[MAX_ADDR_LIST_LEN]; + unsigned int got_domain:1; + unsigned int got_user:1; unsigned int got_password:1; }; const char *thisprogram; int verboseflag = 0; int fakemnt = 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 char * user_name = NULL; -char * domain_name = NULL; char * prefixpath = NULL; const char *cifs_fstype = "cifs"; @@ -254,9 +257,6 @@ check_fstab(const char *progname, char *mountpoint, char *devname, BB end finish BB */ -static char * check_for_domain(char **); - - static int mount_cifs_usage(FILE *stream) { @@ -291,12 +291,56 @@ static char * getusername(void) { char *username = NULL; struct passwd *password = getpwuid(getuid()); - if (password) { + if (password) username = password->pw_name; - } return username; } +/* + * Parse a username string into parsed_mount_info fields. The format is: + * + * DOMAIN\username%password + * + * ...obviously the only required component is "username". The source string + * is modified in the process, but it should remain unchanged at the end. + */ +static void +parse_username(char *rawuser, struct parsed_mount_info *parsed_info) +{ + char *user, *password, slash; + + /* everything after first % sign is a password */ + password = strchr(rawuser, '%'); + if (password) { + *(password) = '\0'; + strlcpy(parsed_info->password, password + 1, + sizeof(parsed_info->password)); + parsed_info->got_password = 1; + } + + /* everything after first '/' or '\' is a username */ + user = strchr(rawuser, '/'); + if (!user) + user = strchr(rawuser, '\\'); + + /* everything before that slash is a domain */ + if (user) { + slash = *user; + *user = '\0'; + strlcpy(parsed_info->domain, rawuser, + sizeof(parsed_info->domain)); + *(user++) = slash; + parsed_info->got_domain = 1; + } else { + user = rawuser; + } + + strlcpy(parsed_info->username, user, sizeof(parsed_info->username)); + parsed_info->got_user = 1; + if (password) + *password = '%'; +} + static int open_cred_file(char *file_name, struct parsed_mount_info *parsed_info) { char * line_buf; @@ -342,20 +386,17 @@ static int open_cred_file(char *file_name, struct parsed_mount_info *parsed_info fprintf(stderr, "mount.cifs failed due to malformed username in credentials file\n"); memset(line_buf,0,4096); return EX_USAGE; - } else { - got_user = 1; - user_name = (char *)calloc(1 + length,1); - /* BB adding free of user_name string before exit, - not really necessary but would be cleaner */ - strlcpy(user_name,temp_val, length+1); } + parsed_info->got_user = 1; + strlcpy(parsed_info->username, temp_val, + sizeof(parsed_info->username)); } } else if (strncasecmp("password",line_buf+i,8) == 0) { - temp_val = strchr(line_buf+i,'='); + temp_val = strchr(line_buf+i, '='); if(temp_val) { /* go past equals sign */ temp_val++; - for(length = 0;length<MOUNT_PASSWD_SIZE+1;length++) { + for(length = 0; length < sizeof(parsed_info->password); length++) { if ((temp_val[length] == '\n') || (temp_val[length] == '\0')) { temp_val[length] = '\0'; @@ -377,6 +418,7 @@ static int open_cred_file(char *file_name, struct parsed_mount_info *parsed_info temp_val++; if(verboseflag) fprintf(stderr, "\nDomain %s\n",temp_val); + for(length = 0;length<DOMAIN_SIZE+1;length++) { if ((temp_val[length] == '\n') || (temp_val[length] == '\0')) { @@ -384,19 +426,14 @@ static int open_cred_file(char *file_name, struct parsed_mount_info *parsed_info break; } } + if(length > DOMAIN_SIZE) { fprintf(stderr, "mount.cifs failed: domain in credentials file too long\n"); return EX_USAGE; - } else { - if(domain_name == NULL) { - domain_name = (char *)calloc(DOMAIN_SIZE+1,1); - } else - memset(domain_name,0,DOMAIN_SIZE); - if(domain_name) { - strlcpy(domain_name,temp_val,DOMAIN_SIZE+1); - got_domain = 1; - } } + + strlcpy(parsed_info->domain, temp_val, sizeof(parsed_info->domain)); + parsed_info->got_domain = 1; } } @@ -465,7 +502,6 @@ get_password_from_file(int file_descript, char *filename, struct parsed_mount_in static int parse_options(const char *data, struct parsed_mount_info *parsed_info) { - char *percent_char = NULL; char *value = NULL, *equals = NULL; char *next_keyword = NULL; char *out = parsed_info->options; @@ -518,7 +554,6 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) } 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') { *filesys_flags |= MS_USER; @@ -528,33 +563,12 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) return EX_USAGE; } } else { - if (strnlen(value, 260) < 260) { - got_user=1; - percent_char = strchr(value,'%'); - if(percent_char) { - *percent_char = ','; - if(parsed_info->got_password) - fprintf(stderr, "\nmount.cifs warning - password specified twice\n"); - parsed_info->got_password = 1; - percent_char++; - strlcpy(parsed_info->password, percent_char, sizeof(parsed_info->password)); - /* 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 { + if (strnlen(value, 260) >= 260) { fprintf(stderr, "username too long\n"); return EX_USAGE; } + parse_username(value, parsed_info); + goto nocopy; } } else if (strncmp(data, "pass", 4) == 0) { if (!value || !*value) { @@ -630,12 +644,13 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) fprintf(stderr, "CIFS: invalid domain name\n"); return EX_USAGE; } - if (strnlen(value, DOMAIN_SIZE+1) < DOMAIN_SIZE+1) { - got_domain = 1; - } else { + if (strnlen(value, sizeof(parsed_info->domain)) >= sizeof(parsed_info->domain)) { fprintf(stderr, "domain name too long\n"); return EX_USAGE; } + parsed_info->got_domain = 1; + strlcpy(parsed_info->domain, value, sizeof(parsed_info->domain)); + goto nocopy; } else if (strncmp(data, "cred", 4) == 0) { if (value && *value) { rc = open_cred_file(value, parsed_info); @@ -731,8 +746,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) } else if (strncmp(data, "exec", 4) == 0) { *filesys_flags &= ~MS_NOEXEC; } else if (strncmp(data, "guest", 5) == 0) { - user_name = (char *)calloc(1, 1); - got_user = 1; + parsed_info->got_user = 1; parsed_info->got_password = 1; } else if (strncmp(data, "ro", 2) == 0) { *filesys_flags |= MS_RDONLY; @@ -830,80 +844,6 @@ replace_commas(char *pass) return 0; } -/* Usernames can not have backslash in them and we use - [BB check if usernames can have forward slash in them BB] - backslash as domain\user separator character -*/ -static char * check_for_domain(char **ppuser) -{ - char * original_string; - char * usernm; - char * domainnm; - int original_len; - int len; - int i; - - if(ppuser == NULL) - return NULL; - - original_string = *ppuser; - - if (original_string == NULL) - return NULL; - - original_len = strlen(original_string); - - usernm = strchr(*ppuser,'/'); - if (usernm == NULL) { - usernm = strchr(*ppuser,'\\'); - if (usernm == NULL) - return NULL; - } - - if(got_domain) { - fprintf(stderr, "Domain name specified twice. Username probably malformed\n"); - return NULL; - } - - usernm[0] = 0; - domainnm = *ppuser; - if (domainnm[0] != 0) { - got_domain = 1; - } else { - fprintf(stderr, "null domain\n"); - } - len = strlen(domainnm); - /* reset domainm to new buffer, and copy - domain name into it */ - domainnm = (char *)malloc(len+1); - if(domainnm == NULL) - return NULL; - - strlcpy(domainnm,*ppuser,len+1); - -/* move_string(*ppuser, usernm+1) */ - len = strlen(usernm+1); - - if(len >= original_len) { - /* should not happen */ - return domainnm; - } - - for(i=0;i<original_len;i++) { - if(i<len) - original_string[i] = usernm[i+1]; - else /* stuff with commas to remove last parm */ - original_string[i] = ','; - } - - /* BB add check for more than one slash? - strchr(*ppuser,'/'); - strchr(*ppuser,'\\') - */ - - return domainnm; -} - /* replace all occurances of "from" in a string with "to" */ static void replace_char(char *string, char from, char to, int maxlen) { @@ -1255,12 +1195,13 @@ int main(int argc, char ** argv) } break; case 'u': - got_user = 1; - user_name = optarg; + parsed_info->got_user = 1; + strlcpy(parsed_info->username, optarg, + sizeof(parsed_info->username)); break; case 'd': - domain_name = optarg; /* BB fix this - currently ignored */ - got_domain = 1; + strlcpy(parsed_info->domain, optarg, sizeof(parsed_info->domain)); + parsed_info->got_domain = 1; break; case 'p': strlcpy(parsed_info->password, optarg, sizeof(parsed_info->password)); @@ -1325,13 +1266,6 @@ int main(int argc, char ** argv) if (rc) goto mount_exit; - options = calloc(options_size, 1); - if (!options) { - fprintf(stderr, "Unable to allocate memory.\n"); - rc = EX_SYSERR; - goto mount_exit; - } - if (orgoptions) { rc = parse_options(orgoptions, parsed_info); if (rc) @@ -1384,17 +1318,21 @@ int main(int argc, char ** argv) mountpoint = resolved_path; - if(got_user == 0) { - /* Note that the password will not be retrieved from the - USER env variable (ie user%password form) as there is - already a PASSWD environment varaible */ + if (!parsed_info->got_user) { + /* + * Note that the password will not be retrieved from the + * USER env variable (ie user%password form) as there is + * already a PASSWD environment varaible + */ if (getenv("USER")) - user_name = strdup(getenv("USER")); - if (user_name == NULL) - user_name = getusername(); - got_user = 1; + strlcpy(parsed_info->username, getenv("USER"), + sizeof(parsed_info->username)); + else + strlcpy(parsed_info->username, getusername(), + sizeof(parsed_info->username)); + parsed_info->got_user = 1; } - + if(!parsed_info->got_password) { char *tmp_pass = getpass("Password: "); /* BB obsolete sys call but no good replacement yet. */ @@ -1413,34 +1351,40 @@ int main(int argc, char ** argv) goto mount_exit; } -mount_retry: - if (*options) - strlcat(options, ",", options_size); + /* copy in ver= string. It's not really needed, but what the hell */ + strlcat(parsed_info->options, ",ver=", sizeof(parsed_info->options)); + strlcat(parsed_info->options, OPTIONS_VERSION, sizeof(parsed_info->options)); - strlcat(options, "unc=", options_size); + /* copy in user= string */ + if (parsed_info->got_user) { + strlcat(parsed_info->options, ",user=", + sizeof(parsed_info->options)); + strlcat(parsed_info->options, parsed_info->username, + sizeof(parsed_info->options)); + } + + if (parsed_info->got_domain) { + strlcat(parsed_info->options, ",domain=", + sizeof(parsed_info->options)); + strlcat(parsed_info->options, parsed_info->domain, + sizeof(parsed_info->options)); + } + + options = calloc(options_size, 1); + if (!options) { + fprintf(stderr, "Unable to allocate memory.\n"); + rc = EX_SYSERR; + goto mount_exit; + } + +mount_retry: + strlcpy(options, "unc=", options_size); strlcat(options, share_name, options_size); /* scan backwards and reverse direction of slash */ temp = strrchr(options, '/'); if(temp > options + 6) *temp = '\\'; - if(user_name) { - /* check for syntax like user=domain\user */ - if(got_domain == 0) - domain_name = check_for_domain(&user_name); - strlcat(options,",user=",options_size); - strlcat(options,user_name,options_size); - } - if(retry == 0) { - if(domain_name) { - /* extra length accounted for in option string above */ - strlcat(options,",domain=",options_size); - strlcat(options,domain_name,options_size); - } - } - - strlcat(options,",ver=",options_size); - strlcat(options,OPTIONS_VERSION,options_size); if (*parsed_info->options) { strlcat(options, ",", options_size); |