This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]