mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
winnpc.c: add low-level connect_to_named_pipe() function.
This contains most of the guts of the previously monolithic function new_named_pipe_client(), but it directly returns the HANDLE to the opened pipe, or a string error message on failure. new_named_pipe_client() is now a thin veneer on top of that, which returns a Socket * by wrapping up the HANDLE into a HandleSocket or the error message into an ErrorSocket as appropriate. So it's now possible to connect to a named pipe, using all our usual infrastructure (including in particular the ownership check of the server, to defend against spoofing attacks), without having to have a Socket-capable event loop in progress.
This commit is contained in:
parent
e305974313
commit
39248737a4
@ -55,7 +55,7 @@ static const SocketVtable ErrorSocket_sockvt = {
|
||||
sk_error_peer_info,
|
||||
};
|
||||
|
||||
static Socket *new_error_socket_internal(char *errmsg, Plug *plug)
|
||||
Socket *new_error_socket_consume_string(Plug *plug, char *errmsg)
|
||||
{
|
||||
ErrorSocket *es = snew(ErrorSocket);
|
||||
es->sock.vt = &ErrorSocket_sockvt;
|
||||
@ -73,5 +73,5 @@ Socket *new_error_socket_fmt(Plug *plug, const char *fmt, ...)
|
||||
msg = dupvprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return new_error_socket_internal(msg, plug);
|
||||
return new_error_socket_consume_string(plug, msg);
|
||||
}
|
||||
|
@ -264,8 +264,12 @@ char *get_hostname(void);
|
||||
/*
|
||||
* Trivial socket implementation which just stores an error. Found in
|
||||
* errsock.c.
|
||||
*
|
||||
* The consume_string variant takes an already-formatted dynamically
|
||||
* allocated string, and takes over ownership of that string.
|
||||
*/
|
||||
Socket *new_error_socket_fmt(Plug *plug, const char *fmt, ...);
|
||||
Socket *new_error_socket_consume_string(Plug *plug, char *errmsg);
|
||||
|
||||
/*
|
||||
* Trivial plug that does absolutely nothing. Found in nullplug.c.
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#include "winsecur.h"
|
||||
|
||||
Socket *new_named_pipe_client(const char *pipename, Plug *plug)
|
||||
HANDLE connect_to_named_pipe(const char *pipename, char **err)
|
||||
{
|
||||
HANDLE pipehandle;
|
||||
PSID usersid, pipeowner;
|
||||
@ -33,9 +33,10 @@ Socket *new_named_pipe_client(const char *pipename, Plug *plug)
|
||||
break;
|
||||
|
||||
if (GetLastError() != ERROR_PIPE_BUSY) {
|
||||
return new_error_socket_fmt(
|
||||
plug, "Unable to open named pipe '%s': %s",
|
||||
*err = dupprintf(
|
||||
"Unable to open named pipe '%s': %s",
|
||||
pipename, win_strerror(GetLastError()));
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -46,16 +47,18 @@ Socket *new_named_pipe_client(const char *pipename, Plug *plug)
|
||||
* take excessively long.)
|
||||
*/
|
||||
if (!WaitNamedPipe(pipename, NMPWAIT_USE_DEFAULT_WAIT)) {
|
||||
return new_error_socket_fmt(
|
||||
plug, "Error waiting for named pipe '%s': %s",
|
||||
*err = dupprintf(
|
||||
"Error waiting for named pipe '%s': %s",
|
||||
pipename, win_strerror(GetLastError()));
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((usersid = get_user_sid()) == NULL) {
|
||||
CloseHandle(pipehandle);
|
||||
return new_error_socket_fmt(
|
||||
plug, "Unable to get user SID: %s", win_strerror(GetLastError()));
|
||||
*err = dupprintf(
|
||||
"Unable to get user SID: %s", win_strerror(GetLastError()));
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (p_GetSecurityInfo(pipehandle, SE_KERNEL_OBJECT,
|
||||
@ -63,21 +66,33 @@ Socket *new_named_pipe_client(const char *pipename, Plug *plug)
|
||||
&pipeowner, NULL, NULL, NULL,
|
||||
&psd) != ERROR_SUCCESS) {
|
||||
CloseHandle(pipehandle);
|
||||
return new_error_socket_fmt(
|
||||
plug, "Unable to get named pipe security information: %s",
|
||||
*err = dupprintf(
|
||||
"Unable to get named pipe security information: %s",
|
||||
win_strerror(GetLastError()));
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (!EqualSid(pipeowner, usersid)) {
|
||||
CloseHandle(pipehandle);
|
||||
LocalFree(psd);
|
||||
return new_error_socket_fmt(
|
||||
plug, "Owner of named pipe '%s' is not us", pipename);
|
||||
*err = dupprintf(
|
||||
"Owner of named pipe '%s' is not us", pipename);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
LocalFree(psd);
|
||||
|
||||
return make_handle_socket(pipehandle, pipehandle, NULL, plug, true);
|
||||
return pipehandle;
|
||||
}
|
||||
|
||||
Socket *new_named_pipe_client(const char *pipename, Plug *plug)
|
||||
{
|
||||
char *err = NULL;
|
||||
HANDLE pipehandle = connect_to_named_pipe(pipename, &err);
|
||||
if (pipehandle == INVALID_HANDLE_VALUE)
|
||||
return new_error_socket_consume_string(plug, err);
|
||||
else
|
||||
return make_handle_socket(pipehandle, pipehandle, NULL, plug, true);
|
||||
}
|
||||
|
||||
#endif /* !defined NO_SECURITY */
|
||||
|
@ -373,6 +373,12 @@ Socket *make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H,
|
||||
Socket *new_named_pipe_client(const char *pipename, Plug *plug); /* winnpc */
|
||||
Socket *new_named_pipe_listener(const char *pipename, Plug *plug); /* winnps */
|
||||
|
||||
/* A lower-level function in winnpc.c, which does most of the work of
|
||||
* new_named_pipe_client (including checking the ownership of what
|
||||
* it's connected to), but returns a plain HANDLE instead of wrapping
|
||||
* it into a Socket. */
|
||||
HANDLE connect_to_named_pipe(const char *pipename, char **err);
|
||||
|
||||
/*
|
||||
* Exports from winctrls.c.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user