This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFC] Add login to remote protocol
- From: Stan Shebs <stan at codesourcery dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 09 Apr 2010 15:27:45 -0700
- Subject: [RFC] Add login to remote protocol
This patch is somewhat more specialized than the tracepoint stuff, but
may be of wider interest, so we offer it for your consideration. It
adds a login capability to the remote protocol; the user sets a username
and password in GDB, then upon connection to a target that requires
them, GDB supplies the two. It is completely up to the target what do
with them, for instance it could simply close the connection in response
to a bad login.
The design is simple, and not especially secure, as the password is sent
in the clear - it's mostly appropriate for direct connections or secured
intranets. We don't do anything to conceal the password from the
console, but one could add a non-echoing reader, and write a password
show that kept it concealed.
The patch below is actually somewhat out of date, but it should be
sufficient for discussion, and I'll update it into a real patch if the
consensus is in favor of including this capability in GDB.
Stan
2009-02-04 Stan Shebs <stan@codesourcery.com>
Remote login support.
gdb/
* remote.c (remote_username, remote_password): New globals.
(struct remote_state): New field must_auth.
(PACKET_qAuth): New enum.
(remote_start_remote): Send qAuth if required.
(remote_query_auth): New.
(remote_must_auth_feature): New.
(remote_protocol_features): Add MustAuth.
(_initialize_remote): Add qAuth packet, set commands.
gdb/doc/
* gdb.texinfo (Remote Configuration): Document set remote username
and password.
(General Query Packets): Document qAuth packet and MustAuth feature.
Index: gdb/doc/gdb.texinfo
===================================================================
*** gdb/doc/gdb.texinfo (revision 235760)
--- gdb/doc/gdb.texinfo (revision 235761)
*************** extended-remote}. This should be set to
*** 14180,14185 ****
--- 14180,14195 ----
target system. If it is not set, the target will use a default
filename (e.g.@: the last program run).
+ @item set remote username @var{username}
+ @itemx show remote username
+ Set the username to be sent to targets that require a login. The
+ username is an arbitary string.
+
+ @item set remote password @var{password}
+ @itemx show remote password
+ Set the password to be sent to targets that require a login. The
+ password is an arbitary string. At present it is stored as cleartext.
+
@kindex set tcp
@kindex show tcp
@item set tcp auto-retry on
*************** Here are the currently defined query and
*** 26157,26162 ****
--- 26167,26184 ----
@table @samp
+ @item qAuth:@var{username},@var{password}
+ @cindex @samp{qAuth} packet
+ Request permission to debug the target. The @var{username} and
+ @var{password} are the values from @code{set remote username} and
+ @code{set remote password}, both encoded as hex strings. If the
+ target accepts the username and password, then it replies with
+ @samp{OK}; otherwise it replies with an error and may disconnect on
+ its own. If the target requires a login (@samp{MustAuth} feature),
+ then if this packet is not supplied soon after connection, then the
+ target may choose to return errors to all subsequent packets and/or
+ disconnect.
+
@item qC
@cindex current thread, remote request
@cindex @samp{qC} packet
*************** These are the currently defined stub fea
*** 26599,26604 ****
--- 26621,26631 ----
@tab @samp{-}
@tab No
+ @item @samp{MustAuth}
+ @tab No
+ @tab @samp{-}
+ @tab No
+
@end multitable
These are the currently defined stub features, in more detail:
*************** indicated it supports them in its @samp{
*** 26668,26673 ****
--- 26695,26707 ----
The remote stub understands the @samp{qXfer:osdata:read} packet
((@pxref{qXfer osdata read}).
+ @item MustAuth
+ @value{GDBN} must send an authorization packet @samp{qAuth} and the
+ username/password pair must be accepted, otherwise the target will
+ return an error and refuse to continue with the session. (It is up to
+ the target whether it actually disconnects, or simply does not respond
+ further.)
+
@end table
@item qSymbol::
Index: gdb/remote.c
===================================================================
*** gdb/remote.c (revision 235760)
--- gdb/remote.c (revision 235761)
*************** static void show_remote_protocol_packet_
*** 213,218 ****
--- 213,222 ----
static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
static ptid_t read_ptid (char *buf, char **obuf);
+ struct remote_state;
+
+ static void remote_query_auth (struct remote_state *);
+
static void remote_query_supported (void);
static void remote_check_symbols (struct objfile *objfile);
*************** struct remote_state
*** 305,310 ****
--- 309,318 ----
/* True if the stub reports support for vCont;t. */
int support_vCont_t;
+
+ /* True if the stub requires successful authorization before
+ completing the connection. */
+ int must_auth;
};
/* Returns true if the multi-process extensions are in effect. */
*************** static int remote_async_terminal_ours_p;
*** 589,594 ****
--- 597,608 ----
static char *remote_exec_file = "";
+ /* A username/password pair for targets that want basic
+ authentication. */
+
+ static char *remote_username = "";
+ static char *remote_password = "";
+
/* User configurable variables for the number of characters in a
memory read/write packet. MIN (rsa->remote_packet_size,
*************** enum {
*** 1001,1006 ****
--- 1015,1021 ----
PACKET_vRun,
PACKET_QStartNoAckMode,
PACKET_vKill,
+ PACKET_qAuth,
PACKET_MAX
};
*************** remote_start_remote (struct ui_out *uiou
*** 2525,2530 ****
--- 2540,2549 ----
which later probes to skip. */
remote_query_supported ();
+ /* Before going any further, see if we have permission. */
+ if (rs->must_auth)
+ remote_query_auth (rs);
+
/* Next, we possibly activate noack mode.
If the QStartNoAckMode packet configuration is set to AUTO,
*************** Some events may be lost, rendering furth
*** 2844,2849 ****
--- 2863,2889 ----
return serial_open (name);
}
+ /* Ask the target whether the given username and password is acceptable. */
+
+ static void
+ remote_query_auth (struct remote_state *rs)
+ {
+ int len;
+
+ strcpy (rs->buf, "qAuth:");
+ len = strlen (rs->buf);
+ len += 2 * bin2hex ((gdb_byte *) remote_username, rs->buf + len, 0);
+ rs->buf[len++] = ';';
+ len += 2 * bin2hex ((gdb_byte *) remote_password, rs->buf + len, 0);
+ rs->buf[len++] = '\0';
+
+ putpkt (rs->buf);
+
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ if (strcmp (rs->buf, "OK") != 0)
+ error ("Not authorized to connect\n");
+ }
+
/* This type describes each known response to the qSupported
packet. */
struct protocol_feature
*************** remote_non_stop_feature (const struct pr
*** 2943,2948 ****
--- 2983,2996 ----
rs->non_stop_aware = (support == PACKET_ENABLE);
}
+ static void
+ remote_must_auth_feature (const struct protocol_feature *feature,
+ enum packet_support support, const char *value)
+ {
+ struct remote_state *rs = get_remote_state ();
+ rs->must_auth = (support == PACKET_ENABLE);
+ }
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
*************** static struct protocol_feature remote_pr
*** 2965,2970 ****
--- 3013,3020 ----
PACKET_QStartNoAckMode },
{ "multiprocess", PACKET_DISABLE, remote_multi_process_feature, -1 },
{ "QNonStop", PACKET_DISABLE, remote_non_stop_feature, -1 },
+ { "MustAuth", PACKET_DISABLE, remote_must_auth_feature,
+ PACKET_qAuth },
};
static void
*************** Show the maximum size of the address (in
*** 9118,9123 ****
--- 9168,9176 ----
add_packet_config_cmd (&remote_protocol_packets[PACKET_vKill],
"vKill", "kill", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qAuth],
+ "qAuth", "auth", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
*************** Set the remote pathname for \"run\""), _
*** 9157,9162 ****
--- 9210,9229 ----
Show the remote pathname for \"run\""), NULL, NULL, NULL,
&remote_set_cmdlist, &remote_show_cmdlist);
+ remote_username = xstrdup ("");
+ add_setshow_string_noescape_cmd ("username", class_files,
+ &remote_username, _("\
+ Set the remote username"), _("\
+ Show the remote username"), NULL, NULL, NULL,
+ &remote_set_cmdlist, &remote_show_cmdlist);
+
+ remote_password = xstrdup ("");
+ add_setshow_string_noescape_cmd ("password", class_files,
+ &remote_password, _("\
+ Set the remote password"), _("\
+ Show the remote password"), NULL, NULL, NULL,
+ &remote_set_cmdlist, &remote_show_cmdlist);
+
/* Eventually initialize fileio. See fileio.c */
initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);