From patchwork Fri Mar 26 14:25:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 48637 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.samba.org (fn.samba.org [216.83.154.106]) by ozlabs.org (Postfix) with ESMTP id 7D9ADB7CCD for ; Sat, 27 Mar 2010 01:25:57 +1100 (EST) Received: from fn.samba.org (localhost [127.0.0.1]) by lists.samba.org (Postfix) with ESMTP id DBCEE46669; Fri, 26 Mar 2010 08:25:56 -0600 (MDT) X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on fn.samba.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.8 tests=BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS,SPF_NEUTRAL autolearn=ham version=3.2.5 X-Original-To: linux-cifs-client@lists.samba.org Delivered-To: linux-cifs-client@lists.samba.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by lists.samba.org (Postfix) with ESMTP id CAD7E4663C for ; Fri, 26 Mar 2010 08:25:44 -0600 (MDT) Received: from int-mx05.intmail.prod.int.phx2.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.18]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o2QEPhB9007495 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 26 Mar 2010 10:25:43 -0400 Received: from localhost.localdomain (vpn-10-105.rdu.redhat.com [10.11.10.105]) by int-mx05.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o2QEPdCa026868 for ; Fri, 26 Mar 2010 10:25:43 -0400 From: Jeff Layton To: linux-cifs-client@lists.samba.org Date: Fri, 26 Mar 2010 10:25:28 -0400 Message-Id: <1269613542-6402-6-git-send-email-jlayton@samba.org> In-Reply-To: <1269613542-6402-1-git-send-email-jlayton@samba.org> References: <1269613542-6402-1-git-send-email-jlayton@samba.org> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.18 Subject: [linux-cifs-client] [PATCH 05/19] mount.cifs: add username and domain fields to parsed_mount_info X-BeenThere: linux-cifs-client@lists.samba.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: The Linux CIFS VFS client List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-cifs-client-bounces@lists.samba.org Errors-To: linux-cifs-client-bounces@lists.samba.org From: Jeff Layton ...and fill and use them accordingly. Signed-off-by: Jeff Layton --- 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;lengthpassword); 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) { 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;igot_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);