зеркало из https://github.com/github/putty.git
Load the Windows printing subsystem at run time.
The printing functions are split between winspool.drv and spoolss.dll in a really weird way (who would have guessed that OpenPrinter and ClosePrinter don't live in the same dynamic library?!), but _neither_ of those counts as a system 'known DLL', so linking against either one of these at load time is again a potential DLL hijacking vector.
This commit is contained in:
Родитель
73039b7831
Коммит
793ac87275
2
Recipe
2
Recipe
|
@ -274,7 +274,7 @@ CHARSET = sbcsdat slookup sbcs utf8 toucs fromucs xenc mimeenc macenc localenc
|
||||||
|
|
||||||
# Standard libraries.
|
# Standard libraries.
|
||||||
LIBS = advapi32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib
|
LIBS = advapi32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib
|
||||||
+ shell32.lib imm32.lib winspool.lib ole32.lib
|
+ shell32.lib imm32.lib ole32.lib
|
||||||
|
|
||||||
# Network backend sets. This also brings in the relevant attachment
|
# Network backend sets. This also brings in the relevant attachment
|
||||||
# to proxy.c depending on whether we're crypto-avoidant or not.
|
# to proxy.c depending on whether we're crypto-avoidant or not.
|
||||||
|
|
|
@ -18,11 +18,46 @@ struct printer_job_tag {
|
||||||
HANDLE hprinter;
|
HANDLE hprinter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECL_WINDOWS_FUNCTION(static, BOOL, EnumPrinters,
|
||||||
|
(DWORD, LPTSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD));
|
||||||
|
DECL_WINDOWS_FUNCTION(static, BOOL, OpenPrinter,
|
||||||
|
(LPTSTR, LPHANDLE, LPPRINTER_DEFAULTS));
|
||||||
|
DECL_WINDOWS_FUNCTION(static, BOOL, ClosePrinter, (HANDLE));
|
||||||
|
DECL_WINDOWS_FUNCTION(static, BOOL, StartDocPrinter, (HANDLE, DWORD, LPBYTE));
|
||||||
|
DECL_WINDOWS_FUNCTION(static, BOOL, EndDocPrinter, (HANDLE));
|
||||||
|
DECL_WINDOWS_FUNCTION(static, BOOL, StartPagePrinter, (HANDLE));
|
||||||
|
DECL_WINDOWS_FUNCTION(static, BOOL, EndPagePrinter, (HANDLE));
|
||||||
|
DECL_WINDOWS_FUNCTION(static, BOOL, WritePrinter,
|
||||||
|
(HANDLE, LPVOID, DWORD, LPDWORD));
|
||||||
|
|
||||||
|
static void init_winfuncs(void)
|
||||||
|
{
|
||||||
|
static int initialised = FALSE;
|
||||||
|
char buf[4096];
|
||||||
|
if (initialised)
|
||||||
|
return;
|
||||||
|
{
|
||||||
|
HMODULE winspool_module = load_system32_dll("winspool.drv");
|
||||||
|
HMODULE spoolss_module = load_system32_dll("spoolss.dll");
|
||||||
|
GET_WINDOWS_FUNCTION_PP(winspool_module, EnumPrinters);
|
||||||
|
GET_WINDOWS_FUNCTION_PP(winspool_module, OpenPrinter);
|
||||||
|
GET_WINDOWS_FUNCTION_PP(spoolss_module, ClosePrinter);
|
||||||
|
GET_WINDOWS_FUNCTION_PP(winspool_module, StartDocPrinter);
|
||||||
|
GET_WINDOWS_FUNCTION_PP(spoolss_module, EndDocPrinter);
|
||||||
|
GET_WINDOWS_FUNCTION_PP(spoolss_module, StartPagePrinter);
|
||||||
|
GET_WINDOWS_FUNCTION_PP(spoolss_module, EndPagePrinter);
|
||||||
|
GET_WINDOWS_FUNCTION_PP(spoolss_module, WritePrinter);
|
||||||
|
}
|
||||||
|
initialised = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static int printer_add_enum(int param, DWORD level, char **buffer,
|
static int printer_add_enum(int param, DWORD level, char **buffer,
|
||||||
int offset, int *nprinters_ptr)
|
int offset, int *nprinters_ptr)
|
||||||
{
|
{
|
||||||
DWORD needed = 0, nprinters = 0;
|
DWORD needed = 0, nprinters = 0;
|
||||||
|
|
||||||
|
init_winfuncs();
|
||||||
|
|
||||||
*buffer = sresize(*buffer, offset+512, char);
|
*buffer = sresize(*buffer, offset+512, char);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -30,16 +65,16 @@ static int printer_add_enum(int param, DWORD level, char **buffer,
|
||||||
* we'll need for the output. Discard the return value since it
|
* we'll need for the output. Discard the return value since it
|
||||||
* will almost certainly be a failure due to lack of space.
|
* will almost certainly be a failure due to lack of space.
|
||||||
*/
|
*/
|
||||||
EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset), 512,
|
p_EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset), 512,
|
||||||
&needed, &nprinters);
|
&needed, &nprinters);
|
||||||
|
|
||||||
if (needed < 512)
|
if (needed < 512)
|
||||||
needed = 512;
|
needed = 512;
|
||||||
|
|
||||||
*buffer = sresize(*buffer, offset+needed, char);
|
*buffer = sresize(*buffer, offset+needed, char);
|
||||||
|
|
||||||
if (EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset),
|
if (p_EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset),
|
||||||
needed, &needed, &nprinters) == 0)
|
needed, &needed, &nprinters) == 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
*nprinters_ptr += nprinters;
|
*nprinters_ptr += nprinters;
|
||||||
|
@ -131,19 +166,21 @@ printer_job *printer_start_job(char *printer)
|
||||||
DOC_INFO_1 docinfo;
|
DOC_INFO_1 docinfo;
|
||||||
int jobstarted = 0, pagestarted = 0;
|
int jobstarted = 0, pagestarted = 0;
|
||||||
|
|
||||||
|
init_winfuncs();
|
||||||
|
|
||||||
ret->hprinter = NULL;
|
ret->hprinter = NULL;
|
||||||
if (!OpenPrinter(printer, &ret->hprinter, NULL))
|
if (!p_OpenPrinter(printer, &ret->hprinter, NULL))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
docinfo.pDocName = "PuTTY remote printer output";
|
docinfo.pDocName = "PuTTY remote printer output";
|
||||||
docinfo.pOutputFile = NULL;
|
docinfo.pOutputFile = NULL;
|
||||||
docinfo.pDatatype = "RAW";
|
docinfo.pDatatype = "RAW";
|
||||||
|
|
||||||
if (!StartDocPrinter(ret->hprinter, 1, (LPBYTE)&docinfo))
|
if (!p_StartDocPrinter(ret->hprinter, 1, (LPBYTE)&docinfo))
|
||||||
goto error;
|
goto error;
|
||||||
jobstarted = 1;
|
jobstarted = 1;
|
||||||
|
|
||||||
if (!StartPagePrinter(ret->hprinter))
|
if (!p_StartPagePrinter(ret->hprinter))
|
||||||
goto error;
|
goto error;
|
||||||
pagestarted = 1;
|
pagestarted = 1;
|
||||||
|
|
||||||
|
@ -151,11 +188,11 @@ printer_job *printer_start_job(char *printer)
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (pagestarted)
|
if (pagestarted)
|
||||||
EndPagePrinter(ret->hprinter);
|
p_EndPagePrinter(ret->hprinter);
|
||||||
if (jobstarted)
|
if (jobstarted)
|
||||||
EndDocPrinter(ret->hprinter);
|
p_EndDocPrinter(ret->hprinter);
|
||||||
if (ret->hprinter)
|
if (ret->hprinter)
|
||||||
ClosePrinter(ret->hprinter);
|
p_ClosePrinter(ret->hprinter);
|
||||||
sfree(ret);
|
sfree(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +204,7 @@ void printer_job_data(printer_job *pj, void *data, int len)
|
||||||
if (!pj)
|
if (!pj)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
WritePrinter(pj->hprinter, data, len, &written);
|
p_WritePrinter(pj->hprinter, data, len, &written);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printer_finish_job(printer_job *pj)
|
void printer_finish_job(printer_job *pj)
|
||||||
|
@ -175,8 +212,8 @@ void printer_finish_job(printer_job *pj)
|
||||||
if (!pj)
|
if (!pj)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EndPagePrinter(pj->hprinter);
|
p_EndPagePrinter(pj->hprinter);
|
||||||
EndDocPrinter(pj->hprinter);
|
p_EndDocPrinter(pj->hprinter);
|
||||||
ClosePrinter(pj->hprinter);
|
p_ClosePrinter(pj->hprinter);
|
||||||
sfree(pj);
|
sfree(pj);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче