[PATCH 04/19] mount.cifs: make mountpassword a field in parsed_info

Jeff Layton <[email protected]>
Newsgroups gmane.linux.file-systems.cifs
Message-ID <[email protected]>
From: Jeff Layton <[email protected]>

...rather than a buffer pointed to by a global var

Signed-off-by: Jeff Layton <[email protected]>
---
 mount.cifs.c |  208 ++++++++++++++++++++++------------------------------------
 1 files changed, 78 insertions(+), 130 deletions(-)

diff --git a/mount.cifs.c b/mount.cifs.c
index c0cc13f..86edae8 100644
--- a/mount.cifs.c
+++ b/mount.cifs.c
@@ -125,13 +125,14 @@ struct parsed_mount_info {
 	char		share[MAX_SHARE_LEN];
 	char		prefix[PATH_MAX];
 	char		options[MAX_OPTIONS_LEN];
+	char		password[MOUNT_PASSWD_SIZE + 1];
 	char		address_list[MAX_ADDR_LIST_LEN];
+	unsigned int	got_password:1;
 };
 
 const char *thisprogram;
 int verboseflag = 0;
 int fakemnt = 0;
-static int got_password = 0;
 static int got_user = 0;
 static int got_domain = 0;
 static int got_ip = 0;
@@ -139,7 +140,6 @@ static int got_unc = 0;
 static int got_uid = 0;
 static int got_gid = 0;
 static char * user_name = NULL;
-static char * mountpassword = NULL;
 char * domain_name = NULL;
 char * prefixpath = NULL;
 const char *cifs_fstype = "cifs";
@@ -297,7 +297,7 @@ static char * getusername(void) {
 	return username;
 }
 
-static int open_cred_file(char * file_name)
+static int open_cred_file(char *file_name, struct parsed_mount_info *parsed_info)
 {
 	char * line_buf;
 	char * temp_val;
@@ -364,18 +364,11 @@ static int open_cred_file(char * file_name)
 				}
 				if(length > MOUNT_PASSWD_SIZE) {
 					fprintf(stderr, "mount.cifs failed: password in credentials file too long\n");
-					memset(line_buf,0, 4096);
+					memset(line_buf, 0, 4096);
 					return EX_USAGE;
-				} else {
-					if(mountpassword == NULL) {
-						mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1);
-					} else
-						memset(mountpassword,0,MOUNT_PASSWD_SIZE);
-					if(mountpassword) {
-						strlcpy(mountpassword,temp_val,MOUNT_PASSWD_SIZE+1);
-						got_password = 1;
-					}
 				}
+				strlcpy(parsed_info->password, temp_val, MOUNT_PASSWD_SIZE + 1);
+				parsed_info->got_password = 1;
 			}
                 } else if (strncasecmp("domain",line_buf+i,6) == 0) {
                         temp_val = strchr(line_buf+i,'=');
@@ -413,22 +406,13 @@ static int open_cred_file(char * file_name)
 	return 0;
 }
 
-static int get_password_from_file(int file_descript, char * filename)
+static int
+get_password_from_file(int file_descript, char *filename, struct parsed_mount_info *parsed_info)
 {
 	int rc = 0;
 	int i;
 	char c;
 
-	if(mountpassword == NULL)
-		mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1);
-	else 
-		memset(mountpassword, 0, MOUNT_PASSWD_SIZE);
-
-	if (mountpassword == NULL) {
-		fprintf(stderr, "malloc failed\n");
-		return EX_SYSERR;
-	}
-
 	if(filename != NULL) {
 		rc = access(filename, R_OK);
 		if (rc) {
@@ -453,24 +437,24 @@ static int get_password_from_file(int file_descript, char * filename)
 				close(file_descript);
 			return EX_SYSERR;
 		} else if(rc == 0) {
-			if(mountpassword[0] == 0) {
+			if(parsed_info->password[0] == 0) {
 				if(verboseflag)
 					fprintf(stderr, "\nWarning: null password used since cifs password file empty");
 			}
 			break;
 		} else /* read valid character */ {
 			if((c == 0) || (c == '\n')) {
-				mountpassword[i] = '\0';
+				parsed_info->password[i] = '\0';
 				break;
 			} else 
-				mountpassword[i] = c;
+				parsed_info->password[i] = c;
 		}
 	}
 	if((i == MOUNT_PASSWD_SIZE) && (verboseflag)) {
 		fprintf(stderr, "\nWarning: password longer than %d characters specified in cifs password file",
 			MOUNT_PASSWD_SIZE);
 	}
-	got_password = 1;
+	parsed_info->got_password = 1;
 	if(filename != NULL) {
 		close(file_descript);
 	}
@@ -549,19 +533,15 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info)
 					percent_char = strchr(value,'%');
 					if(percent_char) {
 						*percent_char = ',';
-						if(mountpassword == NULL)
-							mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1);
-						if(mountpassword) {
-							if(got_password)
-								fprintf(stderr, "\nmount.cifs warning - password specified twice\n");
-							got_password = 1;
-							percent_char++;
-							strlcpy(mountpassword, percent_char,MOUNT_PASSWD_SIZE+1);
+						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++;
-							}
+						while(*percent_char != 0) {
+							*percent_char = ',';
+							percent_char++;
 						}
 					}
 					/* this is only case in which the user
@@ -578,20 +558,16 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info)
 			}
 		} else if (strncmp(data, "pass", 4) == 0) {
 			if (!value || !*value) {
-				if(got_password) {
+				if(parsed_info->got_password) {
 					fprintf(stderr, "\npassword specified twice, ignoring second\n");
 				} else
-					got_password = 1;
+					parsed_info->got_password = 1;
 			} else if (strnlen(value, MOUNT_PASSWD_SIZE) < MOUNT_PASSWD_SIZE) {
-				if (got_password) {
+				if (parsed_info->got_password) {
 					fprintf(stderr, "\nmount.cifs warning - password specified twice\n");
 				} else {
-					mountpassword = strndup(value, MOUNT_PASSWD_SIZE);
-					if (!mountpassword) {
-						fprintf(stderr, "mount.cifs error: %s", strerror(ENOMEM));
-						return EX_USAGE;
-					}
-					got_password = 1;
+					strlcpy(parsed_info->password, value, MOUNT_PASSWD_SIZE + 1);
+					parsed_info->got_password = 1;
 				}
 			} else {
 				fprintf(stderr, "password too long\n");
@@ -602,7 +578,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info)
 			if (value) {
 				if (!strncmp(value, "none", 4) ||
 				    !strncmp(value, "krb5", 4))
-					got_password = 1;
+					parsed_info->got_password = 1;
 			}
 		} else if (strncmp(data, "ip", 2) == 0) {
 			if (!value || !*value) {
@@ -662,7 +638,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info)
 			}
 		} else if (strncmp(data, "cred", 4) == 0) {
 			if (value && *value) {
-				rc = open_cred_file(value);
+				rc = open_cred_file(value, parsed_info);
 				if (rc) {
 					fprintf(stderr, "error %d (%s) opening credential file %s\n",
 						rc, strerror(rc), value);
@@ -757,7 +733,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info)
 		} else if (strncmp(data, "guest", 5) == 0) {
 			user_name = (char *)calloc(1, 1);
 			got_user = 1;
-			got_password = 1;
+			parsed_info->got_password = 1;
 		} else if (strncmp(data, "ro", 2) == 0) {
 			*filesys_flags |= MS_RDONLY;
 			goto nocopy;
@@ -829,51 +805,29 @@ nocopy:
 }
 
 /* replace all (one or more) commas with double commas */
-static void check_for_comma(char ** ppasswrd)
+static int
+replace_commas(char *pass)
 {
-	char *new_pass_buf;
-	char *pass;
-	int i,j;
-	int number_of_commas = 0;
-	int len;
-
-	if(ppasswrd == NULL)
-		return;
-	else 
-		(pass = *ppasswrd);
-
-	len = strlen(pass);
-
-	for(i=0;i<len;i++)  {
-		if(pass[i] == ',')
-			number_of_commas++;
-	}
+	/* a little extra buffer to simplify conversion */
+	char tmpbuf[MOUNT_PASSWD_SIZE + 3];
+	int i = 0, j = 0;
 
-	if(number_of_commas == 0)
-		return;
-	if(number_of_commas > MOUNT_PASSWD_SIZE) {
-		/* would otherwise overflow the mount options buffer */
-		fprintf(stderr, "\nInvalid password. Password contains too many commas.\n");
-		return;
-	}
-
-	new_pass_buf = (char *)malloc(len+number_of_commas+1);
-	if(new_pass_buf == NULL)
-		return;
+	/* don't do anything if there are no commas */
+	if (!strchr(pass, ','))
+		return 0;
 
-	for(i=0,j=0;i<len;i++,j++) {
-		new_pass_buf[j] = pass[i];
-		if(pass[i] == ',') {
-			j++;
-			new_pass_buf[j] = pass[i];
+	while (pass[i]) {
+		if (pass[i] == ',')
+			tmpbuf[j++] = ',';
+		tmpbuf[j++] = pass[i++];
+		if (j > MOUNT_PASSWD_SIZE + 1) {
+			fprintf(stderr, "Converted password too long!\n");
+			return EX_USAGE;
 		}
 	}
-	new_pass_buf[len+number_of_commas] = 0;
-
-	SAFE_FREE(*ppasswrd);
-	*ppasswrd = new_pass_buf;
-	
-	return;
+	tmpbuf[j] = '\0';
+	strlcpy(pass, tmpbuf, MOUNT_PASSWD_SIZE + 1);
+	return 0;
 }
 
 /* Usernames can not have backslash in them and we use
@@ -1053,6 +1007,22 @@ parse_server(char **punc_name)
 	return addrlist;
 }
 
+static int
+get_pw_from_env(struct parsed_mount_info *parsed_info)
+{
+	int rc = 0;
+
+	if (getenv("PASSWD")) {
+		strlcpy(parsed_info->password, getenv("PASSWD"), MOUNT_PASSWD_SIZE + 1);
+		parsed_info->got_password = 1;
+	} else if (getenv("PASSWD_FD"))
+		rc = get_password_from_file(atoi(getenv("PASSWD_FD")), NULL, parsed_info);
+	else if (getenv("PASSWD_FILE"))
+		rc = get_password_from_file(0, getenv("PASSWD_FILE"), parsed_info);
+
+	return rc;
+}
+
 static struct option longopts[] = {
 	{ "all", 0, NULL, 'a' },
 	{ "help",0, NULL, 'h' },
@@ -1293,15 +1263,11 @@ int main(int argc, char ** argv)
 			got_domain = 1;
 			break;
 		case 'p':
-			if(mountpassword == NULL)
-				mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1);
-			if(mountpassword) {
-				got_password = 1;
-				strlcpy(mountpassword,optarg,MOUNT_PASSWD_SIZE+1);
-			}
+			strlcpy(parsed_info->password, optarg, sizeof(parsed_info->password));
+			parsed_info->got_password = 1;
 			break;
 		case 'S':
-			rc = get_password_from_file(0 /* stdin */,NULL);
+			rc = get_password_from_file(0, NULL, parsed_info);
 			if (rc)
 				goto mount_exit;
 			break;
@@ -1355,22 +1321,9 @@ int main(int argc, char ** argv)
 		parsed_info->flags |= CIFS_SETUID_FLAGS;
 	}
 
-	if (getenv("PASSWD")) {
-		if(mountpassword == NULL)
-			mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1);
-		if(mountpassword) {
-			strlcpy(mountpassword,getenv("PASSWD"),MOUNT_PASSWD_SIZE+1);
-			got_password = 1;
-		}
-	} else if (getenv("PASSWD_FD")) {
-		rc = get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
-		if (rc)
-			goto mount_exit;
-	} else if (getenv("PASSWD_FILE")) {
-		rc = get_password_from_file(0, getenv("PASSWD_FILE"));
-		if (rc)
-			goto mount_exit;
-	}
+	rc = get_pw_from_env(parsed_info);
+	if (rc)
+		goto mount_exit;
 
 	options = calloc(options_size, 1);
 	if (!options) {
@@ -1442,17 +1395,16 @@ int main(int argc, char ** argv)
 		got_user = 1;
 	}
        
-	if(got_password == 0) {
+	if(!parsed_info->got_password) {
 		char *tmp_pass = getpass("Password: "); /* BB obsolete sys call but
 							   no good replacement yet. */
-		mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1);
-		if (!tmp_pass || !mountpassword) {
+		if (!tmp_pass) {
 			fprintf(stderr, "Password not entered, exiting\n");
 			rc = EX_USAGE;
 			goto mount_exit;
 		}
-		strlcpy(mountpassword, tmp_pass, MOUNT_PASSWD_SIZE+1);
-		got_password = 1;
+		strlcpy(parsed_info->password, tmp_pass, sizeof(parsed_info->password));
+		parsed_info->got_password = 1;
 	}
 
 	if(!share_name) {
@@ -1543,15 +1495,15 @@ mount_retry:
 	if(verboseflag)
 		fprintf(stderr, "\nmount.cifs kernel mount options: %s", options);
 
-	if (mountpassword) {
+	if (parsed_info->got_password) {
 		/*
 		 * Commas have to be doubled, or else they will
 		 * look like the parameter separator
 		 */
 		if(retry == 0)
-			check_for_comma(&mountpassword);
-		strlcat(options,",pass=",options_size);
-		strlcat(options,mountpassword,options_size);
+			replace_commas(parsed_info->password);
+		strlcat(options, ",pass=", options_size);
+		strlcat(options, parsed_info->password, options_size);
 		if (verboseflag)
 			fprintf(stderr, ",pass=********");
 	}
@@ -1648,14 +1600,10 @@ mount_retry:
 	if (rc)
 		rc = EX_FILEIO;
 mount_exit:
-	if(mountpassword) {
-		int len = strlen(mountpassword);
-		memset(mountpassword,0,len);
-		SAFE_FREE(mountpassword);
-	}
-
 	if (addrhead)
 		freeaddrinfo(addrhead);
+	memset(parsed_info->password, 0, sizeof(parsed_info->password));
+	SAFE_FREE(parsed_info);
 	SAFE_FREE(options);
 	SAFE_FREE(orgoptions);
 	SAFE_FREE(resolved_path);
-- 
1.6.6.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.