Panda3D
|
00001 // Filename: pencrypt.cxx 00002 // Created by: drose (01Sep04) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "filename.h" 00016 #include "encrypt_string.h" 00017 #include "pnotify.h" 00018 #include "panda_getopt.h" 00019 #include "preprocess_argv.h" 00020 00021 string password; 00022 bool got_password = false; 00023 string algorithm; 00024 bool got_algorithm = false; 00025 int key_length = -1; 00026 bool got_key_length = false; 00027 int iteration_count = -1; 00028 bool got_iteration_count = false; 00029 00030 void 00031 usage() { 00032 cerr 00033 << "\nUsage:\n" 00034 << " pencrypt [opts] file [file2 file3 ...]\n" 00035 << " pencrypt -o dest_file file\n\n" 00036 00037 << "This program will apply an encryption algorithm to a file (or multiple files),\n" 00038 << "creating an encrypted version of each file which can only be recovered using\n" 00039 << "pdecrypt and the same password that was supplied to pencrypt. The compressed\n" 00040 << "versions are written to a file with the same name as the original, but the\n" 00041 << "extension .pe added to the filename, and the original file is removed\n" 00042 << "(unless the version with -o is used, in which case you can encrypt only one\n" 00043 << "file, you specify the destination file name, and the original file is not\n" 00044 << "removed).\n\n" 00045 00046 00047 << "Note that if you are adding files to a Panda multifile (.mf file) with\n" 00048 << "the multify command, it is not necessary to encrypt them separately;\n" 00049 << "multify has an inline encryption option.\n\n" 00050 00051 << "Options:\n\n" 00052 00053 << " -p \"password\"\n" 00054 << " Specifies the password to use for encryption. There are no\n" 00055 << " restrictions on the password length or contents, but longer passwords\n" 00056 << " are more secure. If this is not specified, the user is prompted from\n" 00057 << " standard input.\n\n" 00058 00059 << " -t Read the file as a text file. This will automatically convert\n" 00060 << " universal end-of-line characters into a newline character, ascii\n" 00061 << " 10.\n\n" 00062 00063 << " -a \"algorithm\"\n" 00064 << " Specifies the particular encryption algorithm to use. The complete\n" 00065 << " set of available algorithms is defined by the current version of\n" 00066 << " OpenSSL. The default algorithm is taken from the encryption-\n" 00067 << " algorithm config variable.\n\n" 00068 00069 << " -k key_length\n" 00070 << " Specifies the key length, in bits, for the selected encryption\n" 00071 << " algorithm. This only makes sense for those algorithms that support\n" 00072 << " a variable key length. The default value is taken from the\n" 00073 << " encryption-key-length config variable.\n\n" 00074 00075 << " -i iteration_count\n" 00076 << " Specifies the number of times the password is hashed to generate\n" 00077 << " a key. The only purpose of this is to make it computationally\n" 00078 << " more expensive for an attacker to search the key space exhaustively.\n" 00079 << " This should be a multiple of 1,000 and should not exceed about 65\n" 00080 << " million; the value 0 indicates just one application of the hashing\n" 00081 << " algorithm. The default value is taken from the encryption-iteration-\n" 00082 << " count config variable.\n\n"; 00083 } 00084 00085 int 00086 main(int argc, char **argv) { 00087 extern char *optarg; 00088 extern int optind; 00089 const char *optstr = "o:p:ta:k:i:h"; 00090 00091 Filename dest_filename; 00092 bool got_dest_filename = false; 00093 bool text_file = false; 00094 00095 preprocess_argv(argc, argv); 00096 int flag = getopt(argc, argv, optstr); 00097 00098 while (flag != EOF) { 00099 switch (flag) { 00100 case 'o': 00101 dest_filename = Filename::from_os_specific(optarg); 00102 got_dest_filename = true; 00103 break; 00104 00105 case 't': 00106 text_file = true; 00107 break; 00108 00109 case 'p': 00110 password = optarg; 00111 got_password = true; 00112 break; 00113 00114 case 'a': 00115 algorithm = optarg; 00116 got_algorithm = true; 00117 break; 00118 00119 case 'k': 00120 key_length = atoi(optarg); 00121 got_key_length = true; 00122 break; 00123 00124 case 'i': 00125 iteration_count = atoi(optarg); 00126 got_iteration_count = true; 00127 break; 00128 00129 case 'h': 00130 case '?': 00131 default: 00132 usage(); 00133 return 1; 00134 } 00135 flag = getopt(argc, argv, optstr); 00136 } 00137 00138 argc -= (optind-1); 00139 argv += (optind-1); 00140 00141 if (argc < 2) { 00142 usage(); 00143 return 1; 00144 } 00145 00146 if (got_dest_filename && argc > 2) { 00147 cerr << "Only one input file allowed in conjunction with -o.\n"; 00148 return 1; 00149 } 00150 00151 bool all_ok = true; 00152 for (int i = 1; i < argc; i++) { 00153 Filename source_file = Filename::from_os_specific(argv[i]); 00154 if (source_file.get_extension() == "pe") { 00155 cerr << source_file << " already ends .pe; skipping.\n"; 00156 } else { 00157 Filename dest_file = dest_filename; 00158 if (!got_dest_filename) { 00159 dest_file = source_file.get_fullpath() + ".pe"; 00160 } 00161 00162 // Open source file 00163 pifstream read_stream; 00164 if (text_file) { 00165 source_file.set_text(); 00166 } else { 00167 source_file.set_binary(); 00168 } 00169 if (!source_file.open_read(read_stream)) { 00170 cerr << "Couldn't read: " << source_file << endl; 00171 all_ok = false; 00172 00173 } else { 00174 // Open destination file 00175 pofstream write_stream; 00176 dest_file.set_binary(); 00177 if (!dest_file.open_write(write_stream, true)) { 00178 cerr << "Failed to open: " << dest_file << endl; 00179 all_ok = false; 00180 00181 } else { 00182 // Prompt for password. 00183 if (!got_password) { 00184 cerr << "Enter password: "; 00185 getline(cin, password); 00186 got_password = true; 00187 } 00188 00189 cerr << dest_file << "\n"; 00190 bool success = encrypt_stream(read_stream, write_stream, password, 00191 algorithm, key_length, iteration_count); 00192 00193 read_stream.close(); 00194 write_stream.close(); 00195 00196 if (!success) { 00197 cerr << "Failure writing " << dest_file << "\n"; 00198 all_ok = false; 00199 dest_file.unlink(); 00200 00201 } else { 00202 if (!got_dest_filename) { 00203 source_file.unlink(); 00204 } 00205 } 00206 } 00207 } 00208 } 00209 } 00210 00211 if (all_ok) { 00212 return 0; 00213 } else { 00214 return 1; 00215 } 00216 }