OpenVAS Libraries  9.0.3
nasl_ssh.c
Go to the documentation of this file.
1 /* openvas-libraries/nasl
2  * $Id$
3  * Description: Implementation of API for SSH functions used by NASL scripts
4  *
5  * Authors:
6  * Michael Wiegand <michael.wiegand@greenbone.net>
7  * Werner Koch <wk@gnupg.org>
8  *
9  * Copyright:
10  * Copyright (C) 2011, 2012 Greenbone Networks GmbH
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26 
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
39 #include <sys/select.h>
40 #include <sys/socket.h>
41 #include <sys/time.h>
42 #include <sys/types.h>
43 #include <stdlib.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include <unistd.h>
50 #include <glib.h>
51 #include <glib/gstdio.h>
52 
53 #include "nasl_tree.h"
54 #include "nasl_global_ctxt.h"
55 #include "nasl_func.h"
56 #include "nasl_var.h"
57 #include "nasl_lex_ctxt.h"
58 #include "exec.h"
59 #include "../misc/plugutils.h"
60 #include "../base/kb.h"
61 #include "nasl_debug.h"
62 #include "../misc/network.h" /* for openvas_get_socket_from_connection */
63 #include "../misc/openvas_logging.h"
64 #include "../misc/prefs.h" /* for prefs_get() */
65 #include "../misc/openvas_ssh.h"
66 
67 #include "nasl_ssh.h"
68 
69 
70 #ifndef DIM
71 # define DIM(v) (sizeof(v)/sizeof((v)[0]))
72 # define DIMof(type,member) DIM(((type *)0)->member)
73 #endif
74 
75 
76 #if SSH_OK != 0
77 # error Oops, libssh ABI changed
78 #endif
79 
80 
81 /* This object is used to keep track of libssh contexts. Because they
82  are pointers they can't be mapped easily to the NASL type system.
83  We would need to define a new type featuring a callback which would
84  be called when that variable will be freed. This is not easy and
85  has several implications. A clean solution requires a decent
86  garbage collector system with an interface to flange arbitrary C
87  subsystems to it. After all we would end up with a complete VM
88  and FFI. We don't want to do that now.
89 
90  Our solution is to track those contexts here and clean up any left
91  over context at the end of a script run. We could use undocumented
92  "on_exit" feature but that one is not well implemented; thus we use
93  explicit code in the interpreter for the cleanup. The scripts are
94  expected to close the sessions, but as long as they don't open too
95  many of them, the system will take care of it at script termination
96  time.
97 
98  We associate each context with a session id, which is a global
99  counter of this process. The simpler version of using slot numbers
100  won't allow for better consistency checks. A session id of 0 marks
101  an unused table entry.
102 
103  Note that we can't reuse a session for another connection. To use a
104  session is always an active or meanwhile broken connection to the
105  server.
106  */
108 {
110  ssh_session session;
111  ssh_channel channel;
112  int sock; /* The associated socket. */
113  int authmethods; /* Bit fields with available
114  authentication methods. */
115  unsigned int authmethods_valid:1; /* Indicating that methods is valid. */
116  unsigned int user_set:1; /* Set if a user has been set for
117  the session. */
118  unsigned int verbose:1; /* Verbose diagnostics. */
119 };
120 
121 
122 #define MAX_SSH_SESSIONS 10
123 static struct session_table_item_s session_table[MAX_SSH_SESSIONS];
124 
125 
126 /* Local prototypes. */
127 static int nasl_ssh_close_hook (int);
128 
129 static void
130 g_string_comma_str (GString *gstr, const char *str)
131 {
132  if (gstr->len)
133  g_string_append (gstr, ",");
134  g_string_append (gstr, str);
135 }
136 
137 /* Wrapper functions to make a future migration to the libssh 0.6 API
138  easier. The idea is that you only need to remove these wrappers
139  and s/my_ssh_/ssh_/ on this file. */
140 
141 #if LIBSSH_VERSION_INT < SSH_VERSION_INT (0, 6, 0)
142 struct my_ssh_key_s
143 {
144  ssh_private_key privkey;
145  int type;
146  ssh_string pubkey_string;
147 };
148 typedef struct my_ssh_key_s *my_ssh_key;
149 
150 /* Release an ssh key object. NULL for KEY is allowed. */
151 static void
152 my_ssh_key_free (my_ssh_key key)
153 {
154  if (!key)
155  return;
156  privatekey_free (key->privkey);
157  ssh_string_free (key->pubkey_string);
158  g_free (key);
159 }
160 
161 /* Remove the temporary directory and its key file. FILENAME is also freed. */
162 static void
163 remove_and_free_temp_key_file (char *filename)
164 {
165  char *p;
166 
167  if (g_remove (filename) && errno != ENOENT)
168  log_legacy_write ("Failed to remove temporary file '%s': %s\n",
169  filename, strerror (errno));
170  p = strrchr (filename, '/');
171  g_assert (p);
172  *p = 0;
173  if (g_rmdir (filename))
174  log_legacy_write ("Failed to remove temporary directory '%s': %s\n",
175  filename, strerror (errno));
176  g_free (filename);
177 }
178 
179 
180 /* Import a base64 formatted key from a memory c-string.
181  *
182  * B64_KEY is a string holding the base64 encoded key. PASSPHRASE is
183  * the passphrase used to unprotect that key; if the key has no
184  * protection NULL may be passed. AUTH_FN and AUTH_DATA are defined
185  * by libssh to allow for an authentication callback (i.e. asking for
186  * the passphrase; it is not used here. The SESSION is required only
187  * for this wrapper.
188  *
189  * On success the a key object is allocated and stored at PKEY. The
190  * caller must free that value. It is suggested that the caller
191  * stores NULL at it before calling the function.
192  *
193  * The function returns 0 on success or a non-zero value on failure.
194  */
195 static int
196 my_ssh_pki_import_privkey_base64(ssh_session session,
197  int verbose,
198  const char *b64_key,
199  const char *passphrase,
200  void *auth_fn,
201  void *auth_data,
202  my_ssh_key *r_pkey)
203 {
204  ssh_private_key ssh_privkey;
205  ssh_public_key ssh_pubkey;
206  gchar *privkey_filename;
207  char key_dir[] = "/tmp/openvas_key_XXXXXX";
208  GError *error;
209  my_ssh_key pkey;
210  char *pkcs8_buffer = NULL;
211 
212  /* Write the private key to a file in a temporary directory. */
213  if (!g_mkdtemp_full (key_dir, S_IRUSR|S_IWUSR|S_IXUSR))
214  {
215  log_legacy_write ("%s: g_mkdtemp_full/mkdtemp failed\n", __FUNCTION__);
216  return SSH_AUTH_ERROR;
217  }
218 
219  privkey_filename = g_strdup_printf ("%s/key", key_dir);
220 
221  read_again:
222  error = NULL;
223  g_file_set_contents (privkey_filename, b64_key, strlen (b64_key), &error);
224  if (error)
225  {
226  log_legacy_write ("Failed to write private key to temporary file: %s\n",
227  error->message);
228  g_error_free (error);
229  remove_and_free_temp_key_file (privkey_filename);
230  g_free (pkcs8_buffer);
231  return SSH_AUTH_ERROR;
232  }
233 
234  /* We should have created the file with approriate permission in the
235  first place. Unfortunately glib does not allow that. */
236  g_chmod (privkey_filename, S_IRUSR | S_IWUSR);
237 
238  ssh_privkey = privatekey_from_file (session, privkey_filename, 0, passphrase);
239  if (!ssh_privkey && verbose)
240  log_legacy_write ("Reading private key from '%s' failed: %s\n",
241  privkey_filename, ssh_get_error (session));
242  if (!ssh_privkey && !pkcs8_buffer)
243  {
244  if (verbose)
245  log_legacy_write ("Converting from PKCS#8 and trying again ...\n");
246 
247  pkcs8_buffer = openvas_ssh_pkcs8_decrypt (b64_key, passphrase);
248  if (pkcs8_buffer)
249  {
250  b64_key = pkcs8_buffer;
251  g_remove (privkey_filename);
252  goto read_again;
253  }
254  }
255  if (pkcs8_buffer)
256  {
257  g_free (pkcs8_buffer);
258  pkcs8_buffer = NULL;
259  if (verbose)
260  log_legacy_write ("... this worked.\n");
261  }
262 
263  remove_and_free_temp_key_file (privkey_filename);
264  privkey_filename = NULL;
265  if (!ssh_privkey)
266  return SSH_AUTH_ERROR;
267 
268  /* Create our key object. */
269  pkey = g_try_malloc0 (sizeof *pkey);
270  if (!pkey)
271  {
272  privatekey_free (ssh_privkey);
273  log_legacy_write ("%s: malloc failed\n", __FUNCTION__);
274  return SSH_AUTH_ERROR;
275  }
276  pkey->privkey = ssh_privkey;
277  pkey->type = ssh_privatekey_type (ssh_privkey);
278  if (pkey->type == SSH_KEYTYPE_UNKNOWN)
279  {
280  my_ssh_key_free (pkey);
281  if (verbose)
282  log_legacy_write ("%s: key type is not known\n", __FUNCTION__);
283  return SSH_AUTH_ERROR;
284  }
285 
286  /* Extract the public key from the private key. */
287  ssh_pubkey = publickey_from_privatekey (ssh_privkey);
288  if (!ssh_pubkey)
289  {
290  my_ssh_key_free (pkey);
291  if (verbose)
292  log_legacy_write ("%s: publickey_from_privatekey failed\n",
293  __FUNCTION__);
294  return SSH_AUTH_ERROR;
295  }
296  pkey->pubkey_string = publickey_to_string (ssh_pubkey);
297  publickey_free (ssh_pubkey);
298  if (!pkey->pubkey_string)
299  {
300  my_ssh_key_free (pkey);
301  if (verbose)
302  log_legacy_write ("%s: publickey_to_string failed\n", __FUNCTION__);
303  return SSH_AUTH_ERROR;
304  }
305 
306  *r_pkey = pkey;
307  return SSH_AUTH_SUCCESS;
308 }
309 
310 
311 /* Try to authenticate with the given public key.
312 
313  To avoid unnecessary processing and user interaction, the following
314  method is provided for querying whether authentication using the
315  given key would be possible.
316 
317  SESSION is the session object. USERNAME should be passed as NULL.
318  It is expected that ssh_options_set has been been used to set the
319  username before the first authentication attempt. The reason is
320  that most servers do not permit changing the username during the
321  authentication phase. KEY is the ssh key object; the function uses
322  only the public key part.
323 
324  Returns:
325 
326  SSH_SUCCESS (0) - The public key is accepted.
327 
328  SSH_AUTH_DENIED - The server doesn't accept that public key as an
329  authentication token.
330 
331  SSH_AUTH_ERROR - A serious error happened.
332 
333  SSH_AUTH_PARTIAL - You have been partially authenticated, you
334  still have to use another method.
335 
336  */
337 static int
338 my_ssh_userauth_try_publickey (ssh_session session,
339  const char *username,
340  const my_ssh_key key)
341 {
342  int rc;
343 
344  (void)username;
345 
346  rc = ssh_userauth_offer_pubkey (session, NULL, key->type, key->pubkey_string);
347  return rc;
348 }
349 
350 
351 /* Authenticate with the given private key.
352 
353  SESSION is the session object. USERNAME should be passed as NULL.
354  It is expected that ssh_options_set has been been used to set the
355  username before the first authentication attempt. The reason is
356  that most servers do not permit changing the username during the
357  authentication phase. KEY is the ssh key object.
358 
359  Returns:
360 
361  SSH_SUCCESS (0) - The public key is accepted.
362 
363  SSH_AUTH_DENIED - The server doesn't accept that key as an
364  authentication token.
365 
366  SSH_AUTH_ERROR - A serious error happened.
367 
368  SSH_AUTH_PARTIAL - You have been partially authenticated, you
369  still have to use another method.
370 
371  */
372 static int
373 my_ssh_userauth_publickey(ssh_session session,
374  const char *username,
375  const my_ssh_key key)
376 {
377  int rc;
378 
379  (void)username;
380 
381  rc = ssh_userauth_pubkey (session, NULL, key->pubkey_string, key->privkey);
382  return rc;
383 }
384 #endif
385 
386 
387 
388 /* Return the next session id. Note that the first session ID we will
389  hand out is an arbitrary high number, this is only to help
390  debugging. This function is also used to setup a hook to the
391  network layer. */
392 static int
393 next_session_id (void)
394 {
395  static int initialized;
396  static int last = 9000;
397  int i;
398 
399  if (!initialized)
400  {
401  add_close_stream_connection_hook (nasl_ssh_close_hook);
402  initialized = 1;
403  }
404 
405 
406  again:
407  last++;
408  /* Because we don't have an unsigned type, it is better to avoid
409  negative values. Thus if LAST turns negative we wrap around to
410  1; this also avoids the verboten zero. */
411  if (last <= 0)
412  last = 1;
413  /* Now it may happen that after wrapping there is still a session id
414  with that new value in use. We can't allow that and check for
415  it. */
416  for (i=0; i < DIM (session_table); i++)
417  if (session_table[i].session_id == last)
418  goto again;
419 
420  return last;
421 }
422 
423 
424 /* Return the port for an SSH connection. It first looks up the port
425  in the preferences, then falls back to the KB, and finally resorts
426  to the standard port. */
427 static unsigned short
428 get_ssh_port (lex_ctxt *lexic)
429 {
430  const char *value;
431  char *port_str;
432  int type;
433  unsigned short port;
434 
435  value = prefs_get ("auth_port_ssh");
436  if (value && (port = (unsigned short)strtoul (value, NULL, 10)) > 0)
437  return port;
438 
439  port_str = plug_get_key (lexic->script_infos, "Services/ssh", &type, 0);
440  if (port_str)
441  {
442  port = GPOINTER_TO_SIZE (port_str);
443  g_free (port_str);
444  if (type == KB_TYPE_INT && (port = GPOINTER_TO_SIZE (port_str)) > 0)
445  return port;
446  }
447 
448  return 22;
449 }
450 
451 extern int lowest_socket;
452 
485 tree_cell *
487 {
488  ssh_session session;
489  tree_cell *retc;
490  const char *hostname, *key_type, *csciphers, *scciphers;
491  int port, sock;
492  int tbl_slot;
493  const char *s;
494  int verbose = 0;
495  int forced_sock = -1;
496 
497  sock = get_int_local_var_by_name (lexic, "socket", 0);
498  if (sock)
499  port = 0; /* The port is ignored if "socket" is given. */
500  else
501  {
502  port = get_int_local_var_by_name (lexic, "port", 0);
503  if (port <= 0)
504  port = get_ssh_port (lexic);
505  }
506 
507  hostname = plug_get_hostname (lexic->script_infos);
508  if (!hostname)
509  {
510  /* Note: We want the hostname even if we are working on an open
511  socket. libssh may use it for example to maintain its
512  known_hosts file. */
513  log_legacy_write ("No hostname available to ssh_connect\n");
514  return NULL;
515  }
516 
517  session = ssh_new ();
518  if (!session)
519  {
520  log_legacy_write ("Failed to allocate a new SSH session\n");
521  return NULL;
522  }
523 
524  if ((s = getenv ("OPENVAS_LIBSSH_DEBUG")))
525  {
526  verbose = 1;
527  if (*s)
528  {
529  int intval = atoi (s);
530 
531  ssh_options_set (session, SSH_OPTIONS_LOG_VERBOSITY, &intval);
532  }
533  }
534 
535  if (ssh_options_set (session, SSH_OPTIONS_HOST, hostname))
536  {
537  log_legacy_write ("Failed to set SSH hostname '%s': %s\n",
538  hostname, ssh_get_error (session));
539  ssh_free (session);
540  return NULL;
541  }
542 
543  key_type = get_str_local_var_by_name (lexic, "keytype");
544 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT (0, 6, 0)
545  if (key_type && ssh_options_set (session, SSH_OPTIONS_HOSTKEYS, key_type))
546  {
547  log_legacy_write ("Failed to set SSH key type '%s': %s",
548  key_type, ssh_get_error (session));
549  ssh_free (session);
550  return NULL;
551  }
552 #else
553  if (key_type)
554  {
555  log_legacy_write ("SSH_OPTIONS_HOSTKEYS not supported");
556  ssh_free (session);
557  return NULL;
558  }
559 #endif
560 
561  csciphers = get_str_local_var_by_name (lexic, "csciphers");
562  if (csciphers && ssh_options_set (session, SSH_OPTIONS_CIPHERS_C_S, csciphers))
563  {
564  log_legacy_write ("Failed to set SSH client to server ciphers '%s': %s",
565  csciphers, ssh_get_error (session));
566  ssh_free (session);
567  return NULL;
568  }
569  scciphers = get_str_local_var_by_name (lexic, "scciphers");
570  if (scciphers && ssh_options_set (session, SSH_OPTIONS_CIPHERS_S_C, scciphers))
571  {
572  log_legacy_write ("Failed to set SSH server to client ciphers '%s': %s",
573  scciphers, ssh_get_error (session));
574  ssh_free (session);
575  return NULL;
576  }
577 
578  if (port)
579  {
580  unsigned int my_port = port;
581 
582  if (ssh_options_set (session, SSH_OPTIONS_PORT, &my_port))
583  {
584  log_legacy_write ("Failed to set SSH port for '%s' to %d: %s\n",
585  hostname, port, ssh_get_error (session));
586  ssh_free (session);
587  return NULL;
588  }
589  }
590  if (sock)
591  {
592  socket_t my_fd = openvas_get_socket_from_connection (sock);
593 
594  if (verbose)
595  log_legacy_write ("Setting SSH fd for '%s' to %d (NASL sock=%d)\n",
596  hostname, my_fd, sock);
597  if (ssh_options_set (session, SSH_OPTIONS_FD, &my_fd))
598  {
600  ("Failed to set SSH fd for '%s' to %d (NASL sock=%d): %s\n",
601  hostname, my_fd, sock, ssh_get_error (session));
602  ssh_free (session);
603  return NULL;
604  }
605  /* Remember the NASL socket. */
606  forced_sock = sock;
607  }
608 
609  /* Find a place in the table to save the session. */
610  for (tbl_slot=0; tbl_slot < DIM (session_table); tbl_slot++)
611  if (!session_table[tbl_slot].session_id)
612  break;
613  if (!(tbl_slot < DIM (session_table)))
614  {
615  if (verbose)
616  log_legacy_write ("No space left in SSH session table\n");
617  ssh_free (session);
618  return NULL;
619  }
620 
621  /* Prepare the session table entry. */
622  session_table[tbl_slot].session = session;
623  session_table[tbl_slot].authmethods_valid = 0;
624  session_table[tbl_slot].user_set = 0;
625  session_table[tbl_slot].verbose = verbose;
626 
627  /* Connect to the host. */
628  if (verbose)
629  log_legacy_write ("Connecting to SSH server '%s' (port %d, sock %d)\n",
630  hostname, port, sock);
631  if (ssh_connect (session))
632  {
633  if (verbose)
634  log_legacy_write ("Failed to connect to SSH server '%s'"
635  " (port %d, sock %d, f=%d): %s\n", hostname, port,
636  sock, forced_sock, ssh_get_error (session));
637  if (forced_sock != -1)
638  {
639  /* If the caller passed us a socket we can't call ssh_free
640  on it because we expect the caller to close that socket
641  himself. Instead we need to setup a table entry so that
642  it will then be close it via nasl_ssh_internal_close. */
643  session_table[tbl_slot].session_id = next_session_id ();
644  session_table[tbl_slot].sock = forced_sock;
645  }
646  else
647  ssh_free (session);
648 
649  /* return 0 to indicate the error. */
650  /* FIXME: Set the last error string. */
651  retc = alloc_typed_cell (CONST_INT);
652  retc->x.i_val = 0;
653  return retc;
654  }
655 
656  /* How that we are connected, save the session. */
657  session_table[tbl_slot].session_id = next_session_id ();
658  session_table[tbl_slot].sock =
659  forced_sock != -1? forced_sock : ssh_get_fd (session);
660  if (lowest_socket == 0 && session_table[tbl_slot].sock > 0)
661  lowest_socket = session_table[tbl_slot].sock;
662 
663  /* Return the session id. */
664  retc = alloc_typed_cell (CONST_INT);
665  retc->x.i_val = session_table[tbl_slot].session_id;
666  return retc;
667 }
668 
669 
670 /* Helper function to find and validate the session id. On error 0 is
671  returned, on success the session id and in this case the slot number
672  from the table is stored at R_SLOT. */
673 static int
674 verify_session_id (int session_id, const char *funcname,
675  int *r_slot, lex_ctxt *lexic)
676 {
677  int tbl_slot;
678  if (session_id <= 0)
679  {
680  if (funcname)
681  nasl_perror (lexic, "Invalid SSH session id %d passed to %s\n",
682  session_id, funcname);
683  return 0;
684  }
685  for (tbl_slot=0; tbl_slot < DIM (session_table); tbl_slot++)
686  if (session_table[tbl_slot].session_id == session_id)
687  break;
688  if (!(tbl_slot < DIM (session_table)))
689  {
690  if (funcname)
691  nasl_perror (lexic, "Bad SSH session id %d passed to %s\n",
692  session_id, funcname);
693  return 0;
694  }
695 
696  *r_slot = tbl_slot;
697  return session_id;
698 }
699 
700 
701 /* Helper for nasl_ssh_disconnect et al. */
702 static void
703 do_nasl_ssh_disconnect (int tbl_slot)
704 {
705  if (session_table[tbl_slot].channel)
706  ssh_channel_free (session_table[tbl_slot].channel);
707  ssh_disconnect (session_table[tbl_slot].session);
708  ssh_free (session_table[tbl_slot].session);
709  session_table[tbl_slot].session_id = 0;
710  session_table[tbl_slot].session = NULL;
711  session_table[tbl_slot].channel = NULL;
712  session_table[tbl_slot].sock = -1;
713 }
714 
715 
736 tree_cell *
738 {
739  int tbl_slot;
740  int session_id;
741 
742  session_id = get_int_var_by_num (lexic, 0, -1);
743  if (!verify_session_id (session_id, NULL, &tbl_slot, lexic))
744  return FAKE_CELL;
745  do_nasl_ssh_disconnect (tbl_slot);
746  return FAKE_CELL;
747 }
748 
749 
764 static int
765 nasl_ssh_close_hook (int sock)
766 {
767  int tbl_slot, session_id;
768 
769  if (sock == -1)
770  return -1;
771 
772  session_id = 0;
773  for (tbl_slot=0; tbl_slot < DIM (session_table); tbl_slot++)
774  {
775  if (session_table[tbl_slot].sock == sock
776  && session_table[tbl_slot].session_id) {
777  session_id = session_table[tbl_slot].session_id;
778  break;
779  }
780  }
781  if (!session_id)
782  return -1;
783  do_nasl_ssh_disconnect (tbl_slot);
784  return 0;
785 }
786 
787 
801 tree_cell *
803 {
804  int tbl_slot, sock, session_id;
805  tree_cell *retc;
806 
807  session_id = 0;
808  sock = get_int_var_by_num (lexic, 0, -1);
809  if (sock != -1)
810  {
811  for (tbl_slot=0; tbl_slot < DIM (session_table); tbl_slot++)
812  if (session_table[tbl_slot].sock == sock
813  && session_table[tbl_slot].session_id) {
814  session_id = session_table[tbl_slot].session_id;
815  break;
816  }
817  }
818 
819  retc = alloc_typed_cell (CONST_INT);
820  retc->x.i_val = session_id;
821  return retc;
822 }
823 
824 
843 tree_cell *
845 {
846  int tbl_slot, sock, session_id;
847  tree_cell *retc;
848 
849  session_id = get_int_var_by_num (lexic, 0, -1);
850  if (!verify_session_id (session_id, "ssh_get_sock", &tbl_slot, lexic))
851  sock = -1;
852  else
853  sock = session_table[tbl_slot].sock;
854 
855  retc = alloc_typed_cell (CONST_INT);
856  retc->x.i_val = sock;
857  return retc;
858 }
859 
860 
861 /* Get the list of supported authentication schemes. Returns 0 if no
862  authentication is required; otherwise non-zero. */
863 static int
864 get_authmethods (int tbl_slot)
865 {
866  int rc;
867  int retc_val = -1;
868  ssh_session session;
869  int verbose;
870  int methods;
871 
872  session = session_table[tbl_slot].session;
873  verbose = session_table[tbl_slot].verbose;
874 
875  rc = ssh_userauth_none (session, NULL);
876  if (rc == SSH_AUTH_SUCCESS)
877  {
878  log_legacy_write ("SSH authentication succeeded using the none method - "
879  "should not happen; very old server?\n");
880  retc_val = 0;
881  methods = 0;
882  goto leave;
883  }
884  else if (rc == SSH_AUTH_DENIED)
885  {
886  methods = ssh_userauth_list (session, NULL);
887  }
888  else
889  {
890  if (verbose)
892  ("SSH server did not return a list of authentication methods"
893  " - trying all\n");
894  methods = (SSH_AUTH_METHOD_NONE
895  | SSH_AUTH_METHOD_PASSWORD
896  | SSH_AUTH_METHOD_PUBLICKEY
897  | SSH_AUTH_METHOD_HOSTBASED
898  | SSH_AUTH_METHOD_INTERACTIVE);
899  }
900 
901  if (verbose)
902  {
903  fputs ("SSH available authentication methods:", stderr);
904  if ((methods & SSH_AUTH_METHOD_NONE))
905  fputs (" none", stderr);
906  if ((methods & SSH_AUTH_METHOD_PASSWORD))
907  fputs (" password", stderr);
908  if ((methods & SSH_AUTH_METHOD_PUBLICKEY))
909  fputs (" publickey", stderr);
910  if ((methods & SSH_AUTH_METHOD_HOSTBASED))
911  fputs (" hostbased", stderr);
912  if ((methods & SSH_AUTH_METHOD_INTERACTIVE))
913  fputs (" keyboard-interactive", stderr);
914  fputs ("\n", stderr);
915  }
916 
917  leave:
918  session_table[tbl_slot].authmethods = methods;
919  session_table[tbl_slot].authmethods_valid = 1;
920 
921  return retc_val;
922 }
923 
924 
955 tree_cell *
957 {
958  int tbl_slot, session_id;
959 
960  session_id = get_int_var_by_num (lexic, 0, -1);
961  if (!verify_session_id (session_id, "ssh_set_login", &tbl_slot, lexic))
962  return NULL; /* Ooops. */
963  if (!session_table[tbl_slot].user_set)
964  {
965  ssh_session session = session_table[tbl_slot].session;
966  kb_t kb;
967  char *username;
968 
969  username = get_str_local_var_by_name (lexic, "login");
970  if (!username)
971  {
972  kb = plug_get_kb (lexic->script_infos);
973  username = kb_item_get_str (kb, "Secret/SSH/login");
974  }
975  if (username && *username &&
976  ssh_options_set (session, SSH_OPTIONS_USER, username))
977  {
978  log_legacy_write ("Failed to set SSH username '%s': %s\n",
979  username, ssh_get_error (session));
980  return NULL; /* Ooops. */
981  }
982  /* In any case mark the user has set. */
983  session_table[tbl_slot].user_set = 1;
984  }
985  return FAKE_CELL;
986 }
987 
988 
1046 tree_cell *
1048 {
1049  int tbl_slot;
1050  int session_id;
1051  ssh_session session;
1052  const char *password = NULL;
1053  const char *privkeystr = NULL;
1054  const char *privkeypass = NULL;
1055  int rc;
1056  kb_t kb;
1057  int retc_val = -1;
1058  int methods;
1059  int verbose;
1060 
1061  session_id = get_int_var_by_num (lexic, 0, -1);
1062  if (!verify_session_id (session_id, "ssh_userauth", &tbl_slot, lexic))
1063  return NULL; /* Ooops. */
1064  session = session_table[tbl_slot].session;
1065  verbose = session_table[tbl_slot].verbose;
1066 
1067  /* Check if we need to set the user. This is done only once per
1068  session. */
1069  if (!session_table[tbl_slot].user_set && !nasl_ssh_set_login (lexic))
1070  return NULL;
1071 
1072  kb = plug_get_kb (lexic->script_infos);
1073  password = get_str_local_var_by_name (lexic, "password");
1074  privkeystr = get_str_local_var_by_name (lexic, "privatekey");
1075  privkeypass = get_str_local_var_by_name (lexic, "passphrase");
1076  if (!password && !privkeystr && !privkeypass)
1077  {
1078  password = kb_item_get_str (kb, "Secret/SSH/password");
1079  privkeystr = kb_item_get_str (kb, "Secret/SSH/privatekey");
1080  privkeypass = kb_item_get_str (kb, "Secret/SSH/passphrase");
1081  }
1082 
1083  /* Get the authentication methods onlye once per session. */
1084  if (!session_table[tbl_slot].authmethods_valid)
1085  {
1086  if (!get_authmethods (tbl_slot))
1087  {
1088  retc_val = 0;
1089  goto leave;
1090  }
1091  }
1092  methods = session_table[tbl_slot].authmethods;
1093 
1094  /* Check whether a password has been given. If so, try to
1095  authenticate using that password. Note that the OpenSSH client
1096  uses a different order it first tries the public key and then the
1097  password. However, the old NASL SSH protocol implementation tries
1098  the password before the public key authentication. Because we
1099  want to be compatible, we do it in that order. */
1100  if (password && (methods & SSH_AUTH_METHOD_PASSWORD))
1101  {
1102  rc = ssh_userauth_password (session, NULL, password);
1103  if (rc == SSH_AUTH_SUCCESS)
1104  {
1105  retc_val = 0;
1106  goto leave;
1107  }
1108 
1109  if (verbose)
1110  log_legacy_write ("SSH password authentication failed for session"
1111  " %d: %s\n", session_id, ssh_get_error (session));
1112  /* Keep on trying. */
1113  }
1114 
1115  if (password && (methods & SSH_AUTH_METHOD_INTERACTIVE))
1116  {
1117  /* Our strategy for kbint is to send the password to the first
1118  prompt marked as non-echo. */
1119  while ((rc = ssh_userauth_kbdint (session, NULL, NULL)) == SSH_AUTH_INFO)
1120  {
1121  const char *s;
1122  int n, nprompt;
1123  char echoflag;
1124  int found_prompt = 0;
1125 
1126  if (verbose)
1127  {
1128  s = ssh_userauth_kbdint_getname (session);
1129  if (s && *s)
1130  log_legacy_write ("SSH kbdint name='%s'\n", s);
1131  s = ssh_userauth_kbdint_getinstruction (session);
1132  if (s && *s)
1133  log_legacy_write ("SSH kbdint instruction='%s'\n", s);
1134  }
1135  nprompt = ssh_userauth_kbdint_getnprompts (session);
1136  for (n=0; n < nprompt; n++)
1137  {
1138  s = ssh_userauth_kbdint_getprompt (session, n, &echoflag);
1139  if (s && *s && verbose)
1140  log_legacy_write ("SSH kbdint prompt='%s'%s\n",
1141  s, echoflag ? "" : " [hide input]");
1142  if (s && *s && !echoflag && !found_prompt)
1143  {
1144  found_prompt = 1;
1145  rc = ssh_userauth_kbdint_setanswer (session, n, password);
1146  if (rc != SSH_AUTH_SUCCESS)
1147  {
1148  if (verbose)
1150  ("SSH keyboard-interactive authentication "
1151  "failed at prompt %d for session %d: %s\n",
1152  n, session_id, ssh_get_error (session));
1153  }
1154  }
1155  }
1156  }
1157 
1158  if (rc == SSH_AUTH_SUCCESS)
1159  {
1160  retc_val = 0;
1161  goto leave;
1162  }
1163 
1164  if (verbose)
1166  ("SSH keyboard-interactive authentication failed for session %d"
1167  ": %s\n", session_id, ssh_get_error (session));
1168  /* Keep on trying. */
1169  }
1170 
1171  /* If we have a private key, try public key authentication. */
1172  if (privkeystr && *privkeystr && (methods & SSH_AUTH_METHOD_PUBLICKEY))
1173  {
1174 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT (0, 6, 0)
1175  ssh_key key = NULL;
1176 
1177  if (ssh_pki_import_privkey_base64 (privkeystr, privkeypass, NULL, NULL,
1178  &key))
1179  {
1180  if (verbose)
1182  ("SSH public key authentication failed for "
1183  "session %d: %s\n", session_id, "Error converting provided key");
1184  }
1185  else if (ssh_userauth_try_publickey (session, NULL, key)
1186  != SSH_AUTH_SUCCESS)
1187  {
1188  if (verbose)
1190  ("SSH public key authentication failed for "
1191  "session %d: %s\n", session_id, "Server does not want our key");
1192  }
1193  else if (ssh_userauth_publickey (session, NULL, key) == SSH_AUTH_SUCCESS)
1194  {
1195  retc_val = 0;
1196  ssh_key_free (key);
1197  goto leave;
1198  }
1199  ssh_key_free (key);
1200 
1201 #else
1202 
1203  my_ssh_key key = NULL;
1204 
1205  /* SESSION is only used by our emulation - FIXME: remove it for 0.6. */
1206  if (my_ssh_pki_import_privkey_base64 (session, verbose,
1207  privkeystr, privkeypass,
1208  NULL, NULL, &key))
1209  {
1210  if (verbose)
1212  ("SSH public key authentication failed for "
1213  "session %d: %s\n", session_id, "Error converting provided key");
1214  }
1215  else if (my_ssh_userauth_try_publickey (session, NULL, key)
1216  != SSH_AUTH_SUCCESS)
1217  {
1218  if (verbose)
1220  ("SSH public key authentication failed for "
1221  "session %d: %s\n", session_id, "Server does not want our key");
1222  }
1223  else if (my_ssh_userauth_publickey (session, NULL, key)
1224  == SSH_AUTH_SUCCESS)
1225  {
1226  retc_val = 0;
1227  my_ssh_key_free (key);
1228  goto leave;
1229  }
1230  my_ssh_key_free (key);
1231 #endif
1232  /* Keep on trying. */
1233  }
1234 
1235  if (verbose)
1236  log_legacy_write ("SSH authentication failed for session %d: %s\n",
1237  session_id, "No more authentication methods to try");
1238  leave:
1239  {
1240  tree_cell *retc;
1241 
1242  retc = alloc_typed_cell (CONST_INT);
1243  retc->x.i_val = retc_val;
1244  return retc;
1245  }
1246 }
1247 
1248 
1274 tree_cell *
1276 {
1277  int tbl_slot;
1278  int session_id;
1279  ssh_session session;
1280  int rc;
1281  const char *s = NULL;
1282  int methods;
1283  int verbose;
1284 
1285  session_id = get_int_var_by_num (lexic, 0, -1);
1286  if (!verify_session_id (session_id, "ssh_login_interactive",
1287  &tbl_slot, lexic))
1288  return NULL; /* Ooops. */
1289  session = session_table[tbl_slot].session;
1290  verbose = session_table[tbl_slot].verbose;
1291 
1292  /* Check if we need to set the user. This is done only once per
1293  session. */
1294  if (!session_table[tbl_slot].user_set && !nasl_ssh_set_login (lexic))
1295  return NULL;
1296 
1297  /* Get the authentication methods onlye once per session. */
1298  if (!session_table[tbl_slot].authmethods_valid)
1299  {
1300  if (!get_authmethods (tbl_slot))
1301  {
1302  s = g_strdup ("");
1303  goto leave;
1304  }
1305  }
1306  methods = session_table[tbl_slot].authmethods;
1307 
1308  if (methods & SSH_AUTH_METHOD_INTERACTIVE)
1309  {
1310  /* Our strategy for kbint is to send the password to the first
1311  prompt marked as non-echo. */
1312  while ((rc = ssh_userauth_kbdint (session, NULL, NULL)) == SSH_AUTH_INFO)
1313  {
1314  int n, nprompt;
1315  char echoflag;
1316  int found_prompt = 0;
1317 
1318  if (verbose)
1319  {
1320  s = ssh_userauth_kbdint_getname (session);
1321  if (s && *s)
1322  g_message ("SSH kbdint name='%s'", s);
1323  s = ssh_userauth_kbdint_getinstruction (session);
1324  if (s && *s)
1325  g_message ("SSH kbdint instruction='%s'", s);
1326  }
1327 
1328  nprompt = ssh_userauth_kbdint_getnprompts (session);
1329  for (n=0; n < nprompt; n++)
1330  {
1331  s = ssh_userauth_kbdint_getprompt (session, n, &echoflag);
1332  if (s && *s && verbose)
1333  g_message ("SSH kbdint prompt='%s'%s",
1334  s, echoflag ? "" : " [hide input]");
1335  if (s && *s && !echoflag && !found_prompt)
1336  goto leave;
1337  }
1338  }
1339  if (verbose)
1340  g_message
1341  ("SSH keyboard-interactive authentication failed for session %d"
1342  ": %s", session_id, ssh_get_error (session));
1343  }
1344 
1345  if (!s)
1346  return NULL;
1347 
1348  leave:
1349  {
1350  tree_cell *retc;
1351 
1352  retc = alloc_typed_cell (CONST_DATA);
1353  retc->x.str_val = g_strdup (s);
1354  retc->size = strlen (s);
1355  return retc;
1356  }
1357 }
1358 
1359 
1386 tree_cell *
1388 {
1389  int tbl_slot;
1390  int session_id;
1391  ssh_session session;
1392  const char *password = NULL;
1393  int rc;
1394  int retc_val = -1;
1395  int verbose;
1396 
1397  session_id = get_int_var_by_num (lexic, 0, -1);
1398  if (!verify_session_id (session_id, "ssh_login_interactive_pass",
1399  &tbl_slot, lexic))
1400  return NULL; /* Ooops. */
1401  session = session_table[tbl_slot].session;
1402  verbose = session_table[tbl_slot].verbose;
1403 
1404  /* A prompt is waiting for the password. */
1405  if ((password = get_str_local_var_by_name (lexic, "password")) == NULL)
1406  return NULL;
1407 
1408  rc = ssh_userauth_kbdint_setanswer (session, 0, password);
1409 
1410  if (rc < 0)
1411  {
1412  if (verbose)
1413  g_message ("SSH keyboard-interactive authentication "
1414  "failed at prompt %d for session %d: %s",
1415  0, session_id, ssh_get_error (session));
1416  retc_val = -1;
1417  goto leave;
1418  }
1419 
1420  if (rc == 0)
1421  {
1422  /* I need to do that to finish the auth process. */
1423  while ((rc = ssh_userauth_kbdint (session, NULL, NULL)) == SSH_AUTH_INFO)
1424  {
1425  ssh_userauth_kbdint_getnprompts (session);
1426  }
1427  if (rc == SSH_AUTH_SUCCESS)
1428  {
1429  retc_val = 0;
1430  goto leave;
1431  }
1432  if (rc != SSH_AUTH_SUCCESS)
1433  {
1434  retc_val = -1;
1435  goto leave;
1436  }
1437  }
1438 
1439  leave:
1440  {
1441  tree_cell *retc;
1442 
1443  retc = alloc_typed_cell (CONST_INT);
1444  retc->x.i_val = retc_val;
1445  return retc;
1446  }
1447 }
1448 
1449 
1450 static void
1451 exec_ssh_cmd_alarm (int signal)
1452 {
1453  log_legacy_write ("exec_ssh_cmd: Timeout");
1454 }
1455 
1471 static int
1472 exec_ssh_cmd (ssh_session session, char *cmd, int verbose, int compat_mode,
1473  int to_stdout, int to_stderr, GString *response,
1474  GString *compat_buf)
1475 {
1476  int rc, retry = 60;
1477  ssh_channel channel;
1478 
1479  /* Work-around for LibSSH calling poll() with an infinite timeout. */
1480  signal (SIGALRM, exec_ssh_cmd_alarm);
1481  alarm (30);
1482  if ((channel = ssh_channel_new (session)) == NULL)
1483  {
1484  log_legacy_write ("ssh_channel_new failed: %s\n",
1485  ssh_get_error (session));
1486  return SSH_ERROR;
1487  }
1488 
1489  if (ssh_channel_open_session (channel))
1490  {
1491  /* FIXME: Handle SSH_AGAIN. */
1492  if (verbose)
1493  log_legacy_write ("ssh_channel_open_session failed: %s\n",
1494  ssh_get_error (session));
1495  ssh_channel_free (channel);
1496  return SSH_ERROR;
1497  }
1498 
1499  if (ssh_channel_request_pty (channel) && verbose)
1500  g_message ("ssh_channel_request_pty failed: %s", ssh_get_error (session));
1501 
1502  if (ssh_channel_request_exec (channel, cmd))
1503  {
1504  /* FIXME: Handle SSH_AGAIN. */
1505  if (verbose)
1506  log_legacy_write ("ssh_channel_request_exec failed for '%s': %s\n",
1507  cmd, ssh_get_error (session));
1508  ssh_channel_free (channel);
1509  return SSH_ERROR;
1510  }
1511  alarm (0);
1512  signal (SIGALRM, _exit);
1513  /* XXX: ssh_channel_read_timeout() is available for LIBSSH > 0.6. */
1514  while (ssh_channel_is_open (channel) && !ssh_channel_is_eof (channel)
1515  && retry-- > 0)
1516  {
1517  char buffer[4096];
1518 
1519  memset (buffer, '\0', sizeof (buffer));
1520  if ((rc = ssh_channel_read_nonblocking
1521  (channel, buffer, sizeof (buffer), 1)) > 0)
1522  {
1523  if (to_stderr)
1524  g_string_append_len (response, buffer, rc);
1525  if (compat_mode)
1526  g_string_append_len (compat_buf, buffer, rc);
1527  }
1528  if (rc == SSH_ERROR)
1529  goto exec_err;
1530  if ((rc = ssh_channel_read_nonblocking
1531  (channel, buffer, sizeof (buffer), 0)) > 0)
1532  {
1533  compat_mode = 0;
1534  if (to_stdout)
1535  g_string_append_len (response, buffer, rc);
1536  }
1537  if (rc == SSH_ERROR)
1538  goto exec_err;
1539  if (*buffer)
1540  retry = 60;
1541  else
1542  usleep (250000);
1543  }
1544  rc = SSH_OK;
1545 
1546 exec_err:
1547  ssh_channel_free (channel);
1548  return rc;
1549 }
1550 
1602 tree_cell *
1604 {
1605  int tbl_slot;
1606  int session_id;
1607  ssh_session session;
1608  int verbose;
1609  char *cmd;
1610  int rc;
1611  GString *response, *compat_buf;
1612  size_t len = 0;
1613  tree_cell *retc;
1614  char *p;
1615  int to_stdout, to_stderr, compat_mode, compat_buf_inuse;
1616 
1617  session_id = get_int_var_by_num (lexic, 0, -1);
1618  if (!verify_session_id (session_id, "ssh_request_exec", &tbl_slot, lexic))
1619  return NULL;
1620  session = session_table[tbl_slot].session;
1621 
1622  verbose = session_table[tbl_slot].verbose;
1623 
1624  cmd = get_str_local_var_by_name (lexic, "cmd");
1625  if (!cmd || !*cmd)
1626  {
1627  log_legacy_write ("No command passed to ssh_request_exec\n");
1628  return NULL;
1629  }
1630 
1631  to_stdout = get_int_local_var_by_name (lexic, "stdout", -1);
1632  to_stderr = get_int_local_var_by_name (lexic, "stderr", -1);
1633  compat_mode = 0;
1634  if (to_stdout == -1 && to_stderr == -1)
1635  {
1636  /* None of the two named args are given. */
1637  to_stdout = 1;
1638  }
1639  else if (to_stdout == 0 && to_stderr == 0)
1640  {
1641  /* Compatibility mode. */
1642  to_stdout = 1;
1643  compat_mode = 1;
1644  }
1645 
1646  if (to_stdout < 0)
1647  to_stdout = 0;
1648  if (to_stderr < 0)
1649  to_stderr = 0;
1650 
1651 
1652  memset (&compat_buf, '\0', sizeof (compat_buf));
1653  /* Allocate some space in advance. Most commands won't output too
1654  much and thus 512 bytes (6 standard terminal lines) should often
1655  be sufficient. */
1656  response = g_string_sized_new (512);
1657  if (compat_mode)
1658  {
1659  compat_buf = g_string_sized_new (512);
1660  compat_buf_inuse = 1;
1661  }
1662  else
1663  compat_buf_inuse = 0;
1664 
1665  rc = exec_ssh_cmd (session, cmd, verbose, compat_mode, to_stdout, to_stderr,
1666  response, compat_buf);
1667  if (rc == SSH_ERROR)
1668  {
1669  if (compat_buf_inuse)
1670  g_string_free (compat_buf, TRUE);
1671  g_string_free (response, TRUE);
1672  return NULL;
1673  }
1674 
1675  /* Append the compatibility buffer to the output. */
1676  if (compat_buf_inuse)
1677  {
1678  len = compat_buf->len;
1679  p = g_string_free (compat_buf, FALSE);
1680  if (p)
1681  {
1682  g_string_append_len (response, p, len);
1683  g_free (p);
1684  }
1685  }
1686 
1687  /* Return the the output. */
1688  len = response->len;
1689  p = g_string_free (response, FALSE);
1690  if (!p)
1691  {
1692  log_legacy_write ("ssh_request_exec memory problem: %s\n", strerror (-1));
1693  return NULL;
1694  }
1695 
1696  retc = alloc_typed_cell (CONST_DATA);
1697  retc->size = len;
1698  retc->x.str_val = p;
1699  return retc;
1700 }
1701 
1702 
1722 tree_cell *
1724 {
1725  int tbl_slot, session_id;
1726  ssh_session session;
1727  char *banner;
1728  tree_cell *retc;
1729 
1730  session_id = get_int_var_by_num (lexic, 0, -1);
1731  if (!verify_session_id (session_id, "ssh_get_issue_banner", &tbl_slot, lexic))
1732  return NULL;
1733  session = session_table[tbl_slot].session;
1734 
1735  /* We need to make sure that we got the auth methods so that libssh
1736  has the banner. */
1737  if (!session_table[tbl_slot].user_set && !nasl_ssh_set_login (lexic))
1738  return NULL;
1739  if (!session_table[tbl_slot].authmethods_valid)
1740  get_authmethods (tbl_slot);
1741 
1742  banner = ssh_get_issue_banner (session);
1743  if (!banner)
1744  return NULL;
1745 
1746  retc = alloc_typed_cell (CONST_DATA);
1747  retc->x.str_val = g_strdup (banner);
1748  retc->size = strlen (banner);
1749  ssh_string_free_char (banner);
1750  return retc;
1751 }
1752 
1753 
1754 #if LIBSSH_VERSION_INT >= SSH_VERSION_INT (0, 6, 0)
1755 
1773 tree_cell *
1775 {
1776  int tbl_slot, session_id;
1777  ssh_session session;
1778  const char *banner;
1779  tree_cell *retc;
1780 
1781  session_id = get_int_var_by_num (lexic, 0, -1);
1782  if (!verify_session_id (session_id, "ssh_get_server_banner",
1783  &tbl_slot, lexic))
1784  return NULL;
1785  session = session_table[tbl_slot].session;
1786 
1787  //banner = ssh_get_serverbanner (session);
1788  banner = (char*) ssh_get_serverbanner (session);
1789  if (!banner)
1790  return NULL;
1791 
1792  retc = alloc_typed_cell (CONST_DATA);
1793  retc->x.str_val = g_strdup (banner);
1794  retc->size = strlen (banner);
1795  return retc;
1796  (void)lexic;
1797  return NULL;
1798 }
1799 #endif
1800 
1818 tree_cell *
1820 {
1821  int tbl_slot, session_id;
1822  ssh_session session;
1823  ssh_string sstring;
1824  tree_cell *retc;
1825 
1826  session_id = get_int_var_by_num (lexic, 0, -1);
1827  if (!verify_session_id (session_id, "ssh_get_host_key", &tbl_slot, lexic))
1828  return NULL;
1829  session = session_table[tbl_slot].session;
1830 
1831  sstring = ssh_get_pubkey (session);
1832  if (!sstring)
1833  return NULL;
1834 
1835  retc = alloc_typed_cell (CONST_DATA);
1836  retc->x.str_val = ssh_string_to_char (sstring);
1837  retc->size = ssh_string_len (sstring);
1838  ssh_string_free (sstring);
1839  return retc;
1840 }
1841 
1862 tree_cell *
1864 {
1865  int tbl_slot, methods, session_id;
1866  GString *buffer;
1867  char *p;
1868  tree_cell *retc;
1869 
1870  session_id = get_int_var_by_num (lexic, 0, -1);
1871  if (!verify_session_id (session_id, "ssh_get_auth_methods", &tbl_slot, lexic))
1872  return NULL;
1873 
1874  if (!session_table[tbl_slot].user_set && !nasl_ssh_set_login (lexic))
1875  return NULL;
1876  if (!session_table[tbl_slot].authmethods_valid)
1877  get_authmethods (tbl_slot);
1878 
1879  methods = session_table[tbl_slot].authmethods;
1880 
1881  buffer = g_string_sized_new (128);
1882  if ((methods & SSH_AUTH_METHOD_NONE))
1883  g_string_comma_str (buffer, "none");
1884  if ((methods & SSH_AUTH_METHOD_PASSWORD))
1885  g_string_comma_str (buffer, "password");
1886  if ((methods & SSH_AUTH_METHOD_PUBLICKEY))
1887  g_string_comma_str (buffer, "publickey");
1888  if ((methods & SSH_AUTH_METHOD_HOSTBASED))
1889  g_string_comma_str (buffer, "hostbased");
1890  if ((methods & SSH_AUTH_METHOD_INTERACTIVE))
1891  g_string_comma_str (buffer, "keyboard-interactive");
1892  g_string_append_c (buffer, 0x00);
1893  p = g_string_free (buffer, FALSE);
1894  if (!p)
1895  return NULL;
1896 
1897  retc = alloc_typed_cell (CONST_DATA);
1898  retc->x.str_val = p;
1899  retc->size = strlen (p);
1900  return retc;
1901 }
1902 
1903 static void
1904 request_ssh_shell_alarm (int signal)
1905 {
1906  log_legacy_write ("request_ssh_shell: Timeout");
1907 }
1908 
1916 static int
1917 request_ssh_shell (ssh_channel channel)
1918 {
1919  assert (channel);
1920 
1921  /* Work-around for LibSSH calling poll() with an infinite timeout. */
1922  signal (SIGALRM, request_ssh_shell_alarm);
1923  alarm (30);
1924  if (ssh_channel_request_pty (channel))
1925  return -1;
1926  if (ssh_channel_change_pty_size (channel, 80, 24))
1927  return -1;
1928  if (ssh_channel_request_shell (channel))
1929  return -1;
1930  alarm (0);
1931  signal (SIGALRM, _exit);
1932 
1933  return 0;
1934 }
1935 
1950 tree_cell *
1952 {
1953  int tbl_slot, session_id;
1954  ssh_channel channel;
1955  ssh_session session;
1956  tree_cell *retc;
1957 
1958  session_id = get_int_var_by_num (lexic, 0, -1);
1959  if (!verify_session_id (session_id, "ssh_shell_open", &tbl_slot, lexic))
1960  return NULL;
1961  session = session_table[tbl_slot].session;
1962  channel = ssh_channel_new (session);
1963  if (!channel)
1964  return NULL;
1965  if (ssh_channel_open_session (channel))
1966  {
1967  log_legacy_write ("ssh_channel_open_session: %s",
1968  ssh_get_error (session));
1969  ssh_channel_free (channel);
1970  return NULL;
1971  }
1972 
1973  if (request_ssh_shell (channel))
1974  {
1975  log_legacy_write ("request_ssh_shell: %s", ssh_get_error (session));
1976  ssh_channel_free (channel);
1977  return NULL;
1978  }
1979  if (session_table[tbl_slot].channel)
1980  ssh_channel_free (session_table[tbl_slot].channel);
1981  session_table[tbl_slot].channel = channel;
1982 
1983  retc = alloc_typed_cell (CONST_INT);
1984  retc->x.i_val = session_table[tbl_slot].session_id;
1985  return retc;
1986 }
1987 
1996 static int
1997 read_ssh_nonblocking (ssh_channel channel, GString *response)
1998 {
1999  int rc;
2000  char buffer[4096];
2001 
2002  if (!ssh_channel_is_open (channel) || ssh_channel_is_eof (channel))
2003  return -1;
2004 
2005  if ((rc = ssh_channel_read_nonblocking
2006  (channel, buffer, sizeof (buffer), 1)) > 0)
2007  g_string_append_len (response, buffer, rc);
2008  if (rc == SSH_ERROR)
2009  return -1;
2010  if ((rc = ssh_channel_read_nonblocking
2011  (channel, buffer, sizeof (buffer), 0)) > 0)
2012  g_string_append_len (response, buffer, rc);
2013  if (rc == SSH_ERROR)
2014  return -1;
2015  return 0;
2016 }
2017 
2032 tree_cell *
2034 {
2035  int tbl_slot, session_id;
2036  ssh_channel channel;
2037  tree_cell *retc;
2038  GString *response;
2039 
2040  session_id = get_int_var_by_num (lexic, 0, -1);
2041  if (!verify_session_id (session_id, "ssh_shell_read", &tbl_slot, lexic))
2042  return NULL;
2043  channel = session_table[tbl_slot].channel;
2044 
2045  response = g_string_new (NULL);
2046  if (read_ssh_nonblocking (channel, response))
2047  return NULL;
2048  retc = alloc_typed_cell (CONST_DATA);
2049  retc->size = response->len;
2050  retc->x.str_val = g_string_free (response, FALSE);
2051  return retc;
2052 }
2053 
2069 tree_cell *
2071 {
2072  int tbl_slot, rc = -1, len, session_id;
2073  ssh_channel channel;
2074  tree_cell *retc;
2075  char *cmd;
2076 
2077  session_id = get_int_var_by_num (lexic, 0, -1);
2078  if (!verify_session_id (session_id, "ssh_shell_write", &tbl_slot, lexic))
2079  goto write_ret;
2080  if (!(channel = session_table[tbl_slot].channel))
2081  {
2082  log_legacy_write ("ssh_shell_write: No shell channel found");
2083  goto write_ret;
2084  }
2085 
2086  cmd = get_str_local_var_by_name (lexic, "cmd");
2087  if (!cmd || !*cmd)
2088  {
2089  log_legacy_write ("ssh_shell_write: No command passed");
2090  goto write_ret;
2091  }
2092  len = strlen (cmd);
2093  if (ssh_channel_write (channel, cmd, len) != len)
2094  {
2095  log_legacy_write ("ssh_shell_write: %s",
2096  ssh_get_error (session_table[tbl_slot].session));
2097  goto write_ret;
2098  }
2099  rc = 0;
2100 
2101 write_ret:
2102  retc = alloc_typed_cell (CONST_INT);
2103  retc->x.i_val = rc;
2104  return retc;
2105 }
2106 
2117 tree_cell *
2119 {
2120  int tbl_slot, session_id;
2121 
2122  session_id = get_int_var_by_num (lexic, 0, -1);
2123  if (!verify_session_id (session_id, "ssh_shell_close", &tbl_slot, lexic))
2124  return NULL;
2125  if (session_table[tbl_slot].channel)
2126  {
2127  ssh_channel_free (session_table[tbl_slot].channel);
2128  session_table[tbl_slot].channel = NULL;
2129  }
2130 
2131  return NULL;
2132 }
#define FAKE_CELL
Definition: nasl_tree.h:120
tree_cell * nasl_ssh_get_server_banner(lex_ctxt *lexic)
Get the server banner.
Definition: nasl_ssh.c:1774
tree_cell * nasl_ssh_shell_open(lex_ctxt *lexic)
Request an ssh shell.
Definition: nasl_ssh.c:1951
tree_cell * nasl_ssh_login_interactive(lex_ctxt *lexic)
Authenticate a user on an ssh connection.
Definition: nasl_ssh.c:1275
Protos and data structures for SSH functions used by NASL scripts.
tree_cell * nasl_ssh_connect(lex_ctxt *lexic)
Connect to the target host via TCP and setup an ssh connection.
Definition: nasl_ssh.c:486
void * plug_get_key(struct arglist *args, char *name, int *type, int single)
Definition: plugutils.c:767
tree_cell * nasl_ssh_shell_close(lex_ctxt *lexic)
Close an ssh shell.
Definition: nasl_ssh.c:2118
char * str_val
Definition: nasl_tree.h:113
int openvas_get_socket_from_connection(int fd)
Definition: network.c:395
ssh_channel channel
Definition: nasl_ssh.c:111
ssh_session session
Definition: nasl_ssh.c:110
void log_legacy_write(const char *format,...)
Legacy function to write a log message.
long int get_int_local_var_by_name(lex_ctxt *, const char *, int)
Definition: nasl_var.c:1240
const gchar * prefs_get(const gchar *key)
Get a string preference value via a key.
Definition: prefs.c:86
unsigned int user_set
Definition: nasl_ssh.c:116
char * get_str_local_var_by_name(lex_ctxt *, const char *)
Definition: nasl_var.c:1262
union TC::@7 x
tree_cell * nasl_ssh_request_exec(lex_ctxt *lexic)
Run a command via ssh.
Definition: nasl_ssh.c:1603
tree_cell * alloc_typed_cell(int typ)
Definition: nasl_tree.c:53
tree_cell * nasl_ssh_userauth(lex_ctxt *lexic)
Authenticate a user on an ssh connection.
Definition: nasl_ssh.c:1047
void add_close_stream_connection_hook(int(*fnc)(int fd))
Register a hook function for close_stream_connection.
Definition: network.c:1660
tree_cell * nasl_ssh_get_host_key(lex_ctxt *lexic)
Get the host key.
Definition: nasl_ssh.c:1819
kb_t plug_get_kb(struct arglist *args)
Definition: plugutils.c:710
Definition: kb.h:48
tree_cell * nasl_ssh_login_interactive_pass(lex_ctxt *lexic)
Authenticate a user on an ssh connection.
Definition: nasl_ssh.c:1387
Top-level KB. This is to be inherited by KB implementations.
Definition: kb.h:102
tree_cell * nasl_ssh_shell_write(lex_ctxt *lexic)
Write string to ssh shell.
Definition: nasl_ssh.c:2070
Definition: nasl_tree.h:105
tree_cell * nasl_ssh_get_issue_banner(lex_ctxt *lexic)
Get the issue banner.
Definition: nasl_ssh.c:1723
char * openvas_ssh_pkcs8_decrypt(const char *pkcs8_key, const char *passphrase)
Decrypts a base64 encrypted ssh private key.
Definition: openvas_ssh.c:40
tree_cell * nasl_ssh_session_id_from_sock(lex_ctxt *lexic)
Given a socket, return the corresponding session id.
Definition: nasl_ssh.c:802
unsigned int authmethods_valid
Definition: nasl_ssh.c:115
unsigned int verbose
Definition: nasl_ssh.c:118
tree_cell * nasl_ssh_set_login(lex_ctxt *lexic)
Set the login name for the authentication.
Definition: nasl_ssh.c:956
long int get_int_var_by_num(lex_ctxt *, int, int)
Definition: nasl_var.c:1226
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition: nasl_debug.c:94
tree_cell * nasl_ssh_get_auth_methods(lex_ctxt *lexic)
Get the list of authmethods.
Definition: nasl_ssh.c:1863
tree_cell * nasl_ssh_get_sock(lex_ctxt *lexic)
Given a session id, return the corresponding socket.
Definition: nasl_ssh.c:844
#define DIM(v)
Definition: nasl_ssh.c:71
long int i_val
Definition: nasl_tree.h:114
tree_cell * nasl_ssh_disconnect(lex_ctxt *lexic)
Disconnect an ssh connection.
Definition: nasl_ssh.c:737
int lowest_socket
Definition: nasl_socket.c:223
struct arglist * script_infos
Definition: nasl_lex_ctxt.h:39
const char * plug_get_hostname(struct arglist *desc)
Definition: plugutils.c:190
tree_cell * nasl_ssh_shell_read(lex_ctxt *lexic)
Read the output of an ssh shell.
Definition: nasl_ssh.c:2033
#define MAX_SSH_SESSIONS
Definition: nasl_ssh.c:122
int size
Definition: nasl_tree.h:110