diff mbox

[linux-cifs-client,04/19] mount.cifs: make mountpassword a field in parsed_info

Message ID 1269613542-6402-5-git-send-email-jlayton@samba.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jeff Layton March 26, 2010, 2:25 p.m. UTC
None
diff mbox

Patch

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);