From 92fff3bd1e6b2deea4ec0f96ead4e5db8f0f2241 Mon Sep 17 00:00:00 2001 From: robocop Date: Sun, 30 Apr 2006 00:39:37 +0000 Subject: [PATCH] Trying to solve the directory traversal issue again. The problem would be better solved in the long term if ISC_expand_filename was informed whether we need to verify the path and file is valid (we are loading it) or only the path is valid (we are creating a new file). --- src/jrd/dyn_def.epp | 21 +++++++++++++++++---- src/jrd/isc_file.cpp | 13 +++++++++++-- src/msgs/facilities.sql | 2 +- src/msgs/messages.sql | 1 + 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/jrd/dyn_def.epp b/src/jrd/dyn_def.epp index a2b909bfaf..3dafcf7b53 100644 --- a/src/jrd/dyn_def.epp +++ b/src/jrd/dyn_def.epp @@ -927,25 +927,36 @@ void DYN_define_file(Global* gbl, try { id = -1; + Firebird::PathName temp_f; + GET_STRING(ptr, temp_f); + if (!ISC_expand_filename(temp_f, false)) + DYN_error_punt(false, 231, NULL, NULL, NULL, NULL, NULL); + // File name is invalid. request = CMP_find_request(tdbb, id = drq_l_files, DYN_REQUESTS); - Firebird::PathName temp_f; - GET_STRING(ptr, temp_f); - ISC_expand_filename(temp_f, false); if (dbb->dbb_filename == temp_f) { DYN_error_punt(false, 166, NULL, NULL, NULL, NULL, NULL); } FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) FIRST 1 X IN RDB$FILES WITH X.RDB$FILE_NAME EQ temp_f.c_str() + if (!DYN_REQUEST(drq_l_files)) + DYN_REQUEST(drq_l_files) = request; + DYN_error_punt(false, 166, NULL, NULL, NULL, NULL, NULL); END_FOR; + + if (!DYN_REQUEST(drq_l_files)) + DYN_REQUEST(drq_l_files) = request; request = CMP_find_request(tdbb, id = drq_s_files, DYN_REQUESTS); STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) X IN RDB$FILES + if (!DYN_REQUEST(drq_s_files)) + DYN_REQUEST(drq_s_files) = request; + temp_f.copyTo(X.RDB$FILE_NAME, sizeof(X.RDB$FILE_NAME)); X.RDB$SHADOW_NUMBER = (SSHORT)shadow_number; X.RDB$FILE_FLAGS = 0; @@ -1001,7 +1012,9 @@ void DYN_define_file(Global* gbl, } else { - DYN_rundown_request(request, drq_s_files); + if (id != -1) + DYN_rundown_request(request, drq_s_files); + DYN_error_punt(true, msg, NULL, NULL, NULL, NULL, NULL); } } diff --git a/src/jrd/isc_file.cpp b/src/jrd/isc_file.cpp index 06f802680c..f4b74ef897 100644 --- a/src/jrd/isc_file.cpp +++ b/src/jrd/isc_file.cpp @@ -699,13 +699,18 @@ static bool ShortToLongPathName(tstring& Path) } // else FindFirstFile will handle relative paths + bool error = false; + if (npos != right) { // We don't allow wilcards as they will be processed by FindFirstFile // and we would get the first matching file. Incidentally, we are disablimg // escape sequences to produce long names beyond MAXPATHLEN with ?? if (Path.find_first_of("*") != npos || Path.find_first_of("?") != npos) + { right = npos; + error = true; + } else { // We'll assume there's a file at the end. If the user typed a dir, @@ -719,7 +724,10 @@ static bool ShortToLongPathName(tstring& Path) // the path one level above should exist, should be a directory but // shouldn't be a system object. if (rc == 0xFFFFFFFF || !(rc & FILE_ATTRIBUTE_DIRECTORY) || rc & FILE_ATTRIBUTE_SYSTEM) + { right = npos; + error = true; + } Path[last] = sep; } @@ -731,7 +739,7 @@ static bool ShortToLongPathName(tstring& Path) // Main parse block - step through path. HANDLE hf = INVALID_HANDLE_VALUE; - const size leftmost = right; + const size leftmost = right; while (npos != right) { @@ -793,6 +801,7 @@ static bool ShortToLongPathName(tstring& Path) // See what FindFirstFile makes of the path so far. if (hf == INVALID_HANDLE_VALUE) { + error = (npos != right); break; } FindClose(hf); @@ -817,7 +826,7 @@ static bool ShortToLongPathName(tstring& Path) } // We failed to find this file. - if (hf == INVALID_HANDLE_VALUE) + if (hf == INVALID_HANDLE_VALUE && error) { return false; } diff --git a/src/msgs/facilities.sql b/src/msgs/facilities.sql index 2bbe833e76..71e8c80d0f 100644 --- a/src/msgs/facilities.sql +++ b/src/msgs/facilities.sql @@ -9,7 +9,7 @@ INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES ('19 INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES ('1996-11-07 13:39:40', 'GRST', 6, 1); */ INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES ('2005-06-05 12:50:00', 'DSQL', 7, 25); -INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES ('2005-10-28 04:35:21', 'DYN', 8, 231); +INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES ('2006-04-23 04:00:00', 'DYN', 8, 232); /* INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES ('1996-11-07 13:39:40', 'FRED', 9, 1); */ diff --git a/src/msgs/messages.sql b/src/msgs/messages.sql index 824e4d6aff..00b5277d33 100644 --- a/src/msgs/messages.sql +++ b/src/msgs/messages.sql @@ -3032,5 +3032,6 @@ INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FL INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('USAGE_DUPSW', 'ISQL_main', 'isql.epp', NULL, 17, 145, NULL, 'switch "%s" or its equivalent used more than once', NULL, NULL); INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('USAGE_DUPDB', 'ISQL_main', 'isql.epp', NULL, 17, 146, NULL, 'more than one database name: "%s", "%s"', NULL, NULL); INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('field_disappeared', 'EVL_assign_to', 'evl.cpp', NULL, 0, 545, NULL, 'Column has been unexpectedly deleted', NULL, NULL); +INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES (NULL, 'dyn_def.epp', 'DYN_define_file', NULL, 8, 231, NULL, 'File name is invalid', NULL, NULL); COMMIT WORK;