1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +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:
Simon Tatham 2020-01-01 18:58:11 +00:00
parent e305974313
commit 39248737a4
4 changed files with 39 additions and 14 deletions

View File

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

View File

@ -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.

View File

@ -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 */

View File

@ -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.
*/