1 /* Portions Copyright (C) 2009-2021 Greenbone Networks GmbH
2  * Based on work Copyright (C) 1998 - 2002 Renaud Deraison
3  *               SSL Support Copyright (C) 2001 Michel Arboi
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 /**
23  * @file network.c
24  * @brief Network Functions.
25  */
26 
27 #include "../nasl/nasl_debug.h" /* for nasl_*_filename */
28 
29 #include <arpa/inet.h> /* for inet_pton */
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <glib.h>
33 #include <gnutls/gnutls.h>
34 #include <gnutls/x509.h>
35 #include <gvm/base/logging.h>
36 #include <gvm/base/networking.h>
37 #include <gvm/base/prefs.h>
38 #include <gvm/util/kb.h>          /* for kb_item_get_str() */
39 #include <gvm/util/serverutils.h> /* for load_gnutls_file */
40 #include <signal.h>
41 #include <stdarg.h>
42 #include <stdio.h> /* for FILE */
43 #include <stdlib.h>
44 #include <string.h>
45 #include <sys/time.h> /* for gettimeofday */
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <unistd.h>
49 #if defined(__DragonFly__)
50 #include <netinet/in.h>
51 #endif
52 
53 #ifdef __FreeBSD__
54 #include <netinet/in.h>
55 #define s6_addr32 __u6_addr.__u6_addr32
56 #endif
57 
58 #include "network.h" /* for socket_close() */
59 #include "plugutils.h"
60 #include "support.h"
61 
62 #define TIMEOUT 20
63 
64 #ifndef INADDR_NONE
65 #define INADDR_NONE 0xffffffff
66 #endif
67 
68 #undef G_LOG_DOMAIN
69 /**
70  * @brief GLib logging domain.
71  */
72 #define G_LOG_DOMAIN "lib  misc"
73 
74 /*----------------------------------------------------------------*
75  * Low-level connection management                                *
76  *----------------------------------------------------------------*/
77 
78 /** OpenVAS "FILE" structure */
79 typedef struct
80 {
81   int fd; /**< socket number, or whatever */
82   /*
83    * "transport" layer code when stream is encapsultated. Negative transport
84    * signals a free descriptor.
85    */
86   openvas_encaps_t transport;
87   char *priority; /**< Malloced "priority" string for certain transports.  */
88   int timeout;    /**< timeout, in seconds. Special values: -2 for default */
89 
90   int port;
91 
92   gnutls_session_t tls_session;              /**< GnuTLS session */
93   gnutls_certificate_credentials_t tls_cred; /**< GnuTLS credentials */
94 
95   pid_t pid; /**< Owner - for debugging only */
96 
97   char *buf; /**< NULL if unbuffered */
98   int bufsz, bufcnt, bufptr;
99   int last_err;
100 } openvas_connection;
101 
102 /**
103  * The role of this offset is:
104  * 1. To detect bugs when the program tries to write to a bad fd
105  * 2. See if a fd is a real socket or a "openvas descriptor". This is a
106  * quick & dirty hack and should be changed!!!
107  */
108 #define OPENVAS_FD_MAX 1024
109 #define OPENVAS_FD_OFF 1000000
110 
111 static openvas_connection connections[OPENVAS_FD_MAX];
112 
113 /**
114  * @brief Object to store a list of hooks for close_stream_connection.
115  */
116 struct csc_hook_s
117 {
118   struct csc_hook_s *next;
119   int (*fnc) (int fd);
120 };
121 
122 /**
123  * @brief Linked list of hooks to be run by close_stream_connection.
124  */
125 static struct csc_hook_s *csc_hooks;
126 
127 /**
128  * OPENVAS_STREAM(x) is TRUE if \<x\> is a OpenVAS-ified fd
129  */
130 #define OPENVAS_STREAM(x) \
131   (((x - OPENVAS_FD_OFF) < OPENVAS_FD_MAX) && ((x - OPENVAS_FD_OFF) >= 0))
132 
133 /**
134  * determine the openvas_connection* from the openvas fd
135  */
136 #define OVAS_CONNECTION_FROM_FD(fd) (connections + ((fd) -OPENVAS_FD_OFF))
137 
138 /**
139  * Same as perror(), but prefixes the data by our pid.
140  */
141 static int
pid_perror(const char * error)142 pid_perror (const char *error)
143 {
144   g_debug ("[%d] %s : %s", getpid (), error, strerror (errno));
145   return 0;
146 }
147 
148 int
stream_get_err(int fd)149 stream_get_err (int fd)
150 {
151   openvas_connection *p;
152 
153   if (!OPENVAS_STREAM (fd))
154     {
155       errno = EINVAL;
156       return -1;
157     }
158 
159   p = OVAS_CONNECTION_FROM_FD (fd);
160   return p->last_err;
161 }
162 
163 /**
164  * @brief Returns a free file descriptor.
165  */
166 static int
get_connection_fd(void)167 get_connection_fd (void)
168 {
169   int i;
170 
171   for (i = 0; i < OPENVAS_FD_MAX; i++)
172     {
173       if (connections[i].pid == 0) /* Not used */
174         {
175           bzero (&(connections[i]), sizeof (connections[i]));
176           connections[i].pid = getpid ();
177           return i + OPENVAS_FD_OFF;
178         }
179     }
180   g_message ("[%d] %s:%d : Out of OpenVAS file descriptors", getpid (),
181              __FILE__, __LINE__);
182   errno = EMFILE;
183   return -1;
184 }
185 
186 static int
release_connection_fd(int fd,int already_closed)187 release_connection_fd (int fd, int already_closed)
188 {
189   openvas_connection *p;
190 
191   if (!OPENVAS_STREAM (fd))
192     {
193       errno = EINVAL;
194       return -1;
195     }
196   p = OVAS_CONNECTION_FROM_FD (fd);
197 
198   g_free (p->buf);
199   p->buf = 0;
200 
201   /* TLS FIXME: we should call gnutls_bye somewhere.  OTOH, the OpenSSL
202    * equivalent SSL_shutdown wasn't called anywhere in the OpenVAS
203    * (libopenvas nor elsewhere) code either.
204    */
205 
206   /* So far, fd is always a socket. If this is changed in the future, this
207    * code shall be fixed. */
208   if (p->fd >= 0)
209     {
210       g_debug ("[%d] release_connection_fd: fd > 0 fd=%d", getpid (), p->fd);
211       if (shutdown (p->fd, 2) < 0)
212         {
213           /*
214            * It's not uncommon to see that one fail, since a lot of
215            * services close the connection before we ask them to
216            * (ie: http), so we don't show this error by default
217            */
218           pid_perror ("release_connection_fd: shutdown()");
219         }
220       if (!already_closed && socket_close (p->fd) < 0)
221         pid_perror ("release_connection_fd: close()");
222     }
223 
224   if (p->tls_session != NULL)
225     gnutls_deinit (p->tls_session);
226   if (p->tls_cred != NULL)
227     gnutls_certificate_free_credentials (p->tls_cred);
228 
229   g_free (p->priority);
230   p->priority = NULL;
231 
232   bzero (p, sizeof (*p));
233   p->transport = -1;
234   p->pid = 0;
235 
236   return 0;
237 }
238 
239 /* ******** Compatibility function ******** */
240 
241 /** @todo TLS FIXME: migrate this to TLS */
242 /** @todo Fix the voidness of the ssl parameter (problematic in 64bit env.)
243  *       here or on caller-side */
244 /**
245  * @param soc Socket to use.
246  */
247 int
openvas_register_connection(int soc,void * ssl,gnutls_certificate_credentials_t certcred,openvas_encaps_t encaps)248 openvas_register_connection (int soc, void *ssl,
249                              gnutls_certificate_credentials_t certcred,
250                              openvas_encaps_t encaps)
251 {
252   int fd;
253   openvas_connection *p;
254 
255   if ((fd = get_connection_fd ()) < 0)
256     return -1;
257   p = OVAS_CONNECTION_FROM_FD (fd);
258 
259   p->tls_session = ssl;
260   p->tls_cred = certcred;
261 
262   p->timeout = TIMEOUT; /* default value */
263   p->port = 0;          /* just used for debug */
264   p->fd = soc;
265   p->transport = encaps;
266   p->priority = NULL;
267   p->last_err = 0;
268 
269   return fd;
270 }
271 
272 int
openvas_deregister_connection(int fd)273 openvas_deregister_connection (int fd)
274 {
275   openvas_connection *p;
276   if (!OPENVAS_STREAM (fd))
277     {
278       errno = EINVAL;
279       return -1;
280     }
281 
282   p = connections + (fd - OPENVAS_FD_OFF);
283   /* Fixme: Code duplicated from release_connection_fd.  Check usage
284      of this function make sure that TLS stuff is also released in
285      case it is used here.  */
286   g_free (p->priority);
287   p->priority = NULL;
288   bzero (p, sizeof (*p));
289   p->transport = -1;
290   return 0;
291 }
292 
293 /*----------------------------------------------------------------*
294  * High-level connection management                               *
295  *----------------------------------------------------------------*/
296 
297 static int __port_closed;
298 
299 static int
unblock_socket(int soc)300 unblock_socket (int soc)
301 {
302   int flags = fcntl (soc, F_GETFL, 0);
303   if (flags < 0)
304     {
305       pid_perror ("fcntl(F_GETFL)");
306       return -1;
307     }
308   if (fcntl (soc, F_SETFL, O_NONBLOCK | flags) < 0)
309     {
310       pid_perror ("fcntl(F_SETFL,O_NONBLOCK)");
311       return -1;
312     }
313   return 0;
314 }
315 
316 static int
block_socket(int soc)317 block_socket (int soc)
318 {
319   int flags = fcntl (soc, F_GETFL, 0);
320   if (flags < 0)
321     {
322       pid_perror ("fcntl(F_GETFL)");
323       return -1;
324     }
325   if (fcntl (soc, F_SETFL, (~O_NONBLOCK) & flags) < 0)
326     {
327       pid_perror ("fcntl(F_SETFL,~O_NONBLOCK)");
328       return -1;
329     }
330   return 0;
331 }
332 
333 /*
334  * Initialize the SSL library (error strings and algorithms) and try
335  * to set the pseudo random generator to something less silly than the
336  * default value: 1 according to SVID 3, BSD 4.3, ISO 9899 :-(
337  */
338 
339 void
tlserror(char * txt,int err)340 tlserror (char *txt, int err)
341 {
342   g_message ("[%d] %s: %s", getpid (), txt, gnutls_strerror (err));
343 }
344 
345 static void
log_message_gnutls(int level,const char * msg)346 log_message_gnutls (int level, const char *msg)
347 {
348   g_debug ("LEVEL %d: %s", level, msg);
349 }
350 
351 /**
352  * @brief Initializes SSL support.
353  */
354 int
openvas_SSL_init()355 openvas_SSL_init ()
356 {
357   gnutls_global_set_log_level (2);
358   gnutls_global_set_log_function (log_message_gnutls);
359 
360   int ret = gnutls_global_init ();
361   if (ret < 0)
362     {
363       tlserror ("gnutls_global_init", ret);
364       return -1;
365     }
366 
367   return 0;
368 }
369 
370 int
openvas_get_socket_from_connection(int fd)371 openvas_get_socket_from_connection (int fd)
372 {
373   openvas_connection *fp;
374 
375   if (!OPENVAS_STREAM (fd))
376     {
377       g_message ("[%d] openvas_get_socket_from_connection: bad fd <%d>",
378                  getpid (), fd);
379       return fd;
380     }
381   fp = connections + (fd - OPENVAS_FD_OFF);
382   if (fp->transport <= 0)
383     {
384       g_message ("openvas_get_socket_from_connection: fd <%d> is closed", fd);
385       return -1;
386     }
387   return fp->fd;
388 }
389 
390 gnutls_session_t
ovas_get_tlssession_from_connection(int fd)391 ovas_get_tlssession_from_connection (int fd)
392 {
393   openvas_connection *fp;
394 
395   if (!OPENVAS_STREAM (fd))
396     return NULL;
397 
398   fp = connections + (fd - OPENVAS_FD_OFF);
399   return fp->tls_session;
400 }
401 
402 /**
403  * Sets the priorities for the GnuTLS session according to encaps.
404  * PRIORITY is used to convey custom priorities; it is only used if ENCAPS is
405  * set to OPENVAS_ENCAPS_TLScustom.
406  */
407 static int
set_gnutls_protocol(gnutls_session_t session,openvas_encaps_t encaps,const char * priority)408 set_gnutls_protocol (gnutls_session_t session, openvas_encaps_t encaps,
409                      const char *priority)
410 {
411   const char *priorities;
412   const char *errloc;
413   int err;
414 
415   switch (encaps)
416     {
417     case OPENVAS_ENCAPS_SSLv3:
418       priorities = "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0:+ARCFOUR-128:%COMPAT";
419       break;
420     case OPENVAS_ENCAPS_TLSv1:
421       priorities = "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:+ARCFOUR-128:%COMPAT";
422       break;
423     case OPENVAS_ENCAPS_TLSv11:
424       priorities = "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1:+ARCFOUR-128:%COMPAT";
425       break;
426     case OPENVAS_ENCAPS_TLSv12:
427       priorities = "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2:+ARCFOUR-128:%COMPAT";
428       break;
429     case OPENVAS_ENCAPS_TLSv13:
430       priorities = "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3:%COMPAT";
431       break;
432     case OPENVAS_ENCAPS_SSLv23: /* Compatibility mode */
433       priorities =
434         "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:+VERS-SSL3.0:+ARCFOUR-128:%COMPAT";
435       break;
436     default:
437       g_debug ("*Bug* at %s:%d. Unknown transport %d", __FILE__, __LINE__,
438                encaps);
439       /* fallthrough */
440     case OPENVAS_ENCAPS_TLScustom:
441       priorities = priority;
442       break;
443     }
444 
445   if ((err = gnutls_priority_set_direct (session, priorities, &errloc)))
446     {
447       g_message ("[%d] setting session priorities '%.20s': %s", getpid (),
448                  errloc, gnutls_strerror (err));
449       return -1;
450     }
451 
452   return 0;
453 }
454 
455 /**
456  * @brief Loads a certificate and the corresponding private key from PEM files.
457  *
458  * The private key may be encrypted, in which case the password to
459  * decrypt the key should be given as the passwd parameter.
460  *
461  * @return Returns 0 on success and -1 on failure.
462  */
463 static int
load_cert_and_key(gnutls_certificate_credentials_t xcred,const char * cert,const char * key,const char * passwd)464 load_cert_and_key (gnutls_certificate_credentials_t xcred, const char *cert,
465                    const char *key, const char *passwd)
466 {
467   gnutls_x509_crt_t x509_crt = NULL;
468   gnutls_x509_privkey_t x509_key = NULL;
469   gnutls_datum_t data;
470   int ret;
471   int result = 0;
472 
473   if (load_gnutls_file (cert, &data))
474     {
475       g_message ("[%d] load_cert_and_key: Error loading cert file %s",
476                  getpid (), cert);
477       result = -1;
478       goto cleanup;
479     }
480   ret = gnutls_x509_crt_init (&x509_crt);
481   if (ret < 0)
482     {
483       tlserror ("gnutls_x509_crt_init", ret);
484       /* x509_crt may be != NULL even if gnutls_x509_crt_init fails */
485       x509_crt = NULL;
486       result = -1;
487       goto cleanup;
488     }
489   ret = gnutls_x509_crt_import (x509_crt, &data, GNUTLS_X509_FMT_PEM);
490   if (ret < 0)
491     {
492       tlserror ("gnutls_x509_crt_import", ret);
493       result = -1;
494       goto cleanup;
495     }
496   unload_gnutls_file (&data);
497 
498   if (load_gnutls_file (key, &data))
499     {
500       g_message ("[%d] load_cert_and_key: Error loading key file %s", getpid (),
501                  key);
502       result = -1;
503       goto cleanup;
504     }
505   ret = gnutls_x509_privkey_init (&x509_key);
506   if (ret < 0)
507     {
508       tlserror ("gnutls_x509_privkey_init", ret);
509       /* x509_key may be != NULL even if gnutls_x509_privkey_init fails */
510       x509_key = NULL;
511       result = -1;
512       goto cleanup;
513     }
514   if (passwd)
515     {
516       ret = gnutls_x509_privkey_import_pkcs8 (x509_key, &data,
517                                               GNUTLS_X509_FMT_PEM, passwd, 0);
518       if (ret < 0)
519         {
520           tlserror ("gnutls_x509_privkey_import_pkcs8", ret);
521           result = -1;
522           goto cleanup;
523         }
524     }
525   else
526     {
527       ret = gnutls_x509_privkey_import (x509_key, &data, GNUTLS_X509_FMT_PEM);
528       if (ret < 0)
529         {
530           tlserror ("gnutls_x509_privkey_import", ret);
531           result = -1;
532           goto cleanup;
533         }
534     }
535   unload_gnutls_file (&data);
536 
537   ret = gnutls_certificate_set_x509_key (xcred, &x509_crt, 1, x509_key);
538   if (ret < 0)
539     {
540       tlserror ("gnutls_certificate_set_x509_key", ret);
541       result = -1;
542       goto cleanup;
543     }
544 
545 cleanup:
546 
547   if (x509_crt)
548     gnutls_x509_crt_deinit (x509_crt);
549   if (x509_key)
550     gnutls_x509_privkey_deinit (x509_key);
551 
552   return result;
553 }
554 
555 static int
is_ip_address(const char * str)556 is_ip_address (const char *str)
557 {
558   struct sockaddr_in sa;
559   struct sockaddr_in6 sa6;
560 
561   if (inet_pton (AF_INET, str, &(sa.sin_addr)) == 1)
562     return 1;
563 
564   return inet_pton (AF_INET6, str, &(sa6.sin6_addr)) == 1;
565 }
566 
567 static int
open_SSL_connection(openvas_connection * fp,const char * cert,const char * key,const char * passwd,const char * cafile,const char * hostname)568 open_SSL_connection (openvas_connection *fp, const char *cert, const char *key,
569                      const char *passwd, const char *cafile,
570                      const char *hostname)
571 {
572   int ret, err, d;
573   time_t tictac;
574   fd_set fdw, fdr;
575   struct timeval to;
576 
577   ret = gnutls_init (&(fp->tls_session), GNUTLS_CLIENT);
578   if (ret < 0)
579     {
580       tlserror ("gnutls_init", ret);
581       return -1;
582     }
583 
584   /* set_gnutls_protocol handles OPENVAS_ENCAPS_SSLv2 by falling back
585    * to OPENVAS_ENCAPS_SSLv23.  However, this function
586    * (open_SSL_connection) is called only by open_stream_connection and
587    * open_stream_connection will exit with an error code if called with
588    * OPENVAS_ENCAPS_SSLv2, so it should never end up calling
589    * open_SSL_connection with OPENVAS_ENCAPS_SSLv2.
590    */
591   if (set_gnutls_protocol (fp->tls_session, fp->transport, fp->priority) < 0)
592     return -1;
593 
594   if (hostname && !is_ip_address (hostname))
595     gnutls_server_name_set (fp->tls_session, GNUTLS_NAME_DNS, hostname,
596                             strlen (hostname));
597 
598   ret = gnutls_certificate_allocate_credentials (&(fp->tls_cred));
599   if (ret < 0)
600     {
601       tlserror ("gnutls_certificate_allocate_credentials", ret);
602       return -1;
603     }
604   ret = gnutls_credentials_set (fp->tls_session, GNUTLS_CRD_CERTIFICATE,
605                                 fp->tls_cred);
606   if (ret < 0)
607     {
608       tlserror ("gnutls_credentials_set", ret);
609       return -1;
610     }
611 
612   if (cert != NULL && key != NULL)
613     {
614       if (load_cert_and_key (fp->tls_cred, cert, key, passwd) < 0)
615         return -1;
616     }
617 
618   if (cafile != NULL)
619     {
620       ret = gnutls_certificate_set_x509_trust_file (fp->tls_cred, cafile,
621                                                     GNUTLS_X509_FMT_PEM);
622       if (ret < 0)
623         {
624           tlserror ("gnutls_certificate_set_x509_trust_file", ret);
625           return -1;
626         }
627     }
628 
629   unblock_socket (fp->fd);
630 
631   gnutls_transport_set_ptr (fp->tls_session,
632                             (gnutls_transport_ptr_t) GSIZE_TO_POINTER (fp->fd));
633 
634   tictac = time (NULL);
635 
636   for (;;)
637     {
638       err = gnutls_handshake (fp->tls_session);
639 
640       if (err == 0)
641         return 1;
642 
643       if (err != GNUTLS_E_INTERRUPTED && err != GNUTLS_E_AGAIN
644           && err != GNUTLS_E_WARNING_ALERT_RECEIVED)
645         {
646           g_debug ("[%d] gnutls_handshake: %s", getpid (),
647                    gnutls_strerror (err));
648           return -1;
649         }
650 
651       FD_ZERO (&fdr);
652       FD_SET (fp->fd, &fdr);
653       FD_ZERO (&fdw);
654       FD_SET (fp->fd, &fdw);
655 
656       do
657         {
658           d = tictac + fp->timeout - time (NULL);
659           if (d <= 0)
660             {
661               fp->last_err = ETIMEDOUT;
662               return -1;
663             }
664           to.tv_sec = d;
665           to.tv_usec = 0;
666           errno = 0;
667           if ((ret = select (fp->fd + 1, &fdr, &fdw, NULL, &to)) <= 0)
668             pid_perror ("select");
669         }
670       while (ret < 0 && errno == EINTR);
671 
672       if (ret <= 0)
673         {
674           fp->last_err = ETIMEDOUT;
675           return -1;
676         }
677     }
678 }
679 
680 /*
681  * @brief Upgrade an ENCAPS_IP socket to an SSL/TLS encapsulated one.
682  *
683  * @param[in]   fd          Socket file descriptor.
684  * @param[in]   transport   Encapsulation type.
685  * @param[in]   arg         Script args.
686  *
687  * @return -1 if error, socket file descriptor value otherwise.
688  */
689 int
socket_negotiate_ssl(int fd,openvas_encaps_t transport,struct script_infos * args)690 socket_negotiate_ssl (int fd, openvas_encaps_t transport,
691                       struct script_infos *args)
692 {
693   char *cert = NULL, *key = NULL, *passwd = NULL, *cafile = NULL;
694   char *hostname = NULL;
695   openvas_connection *fp;
696   kb_t kb;
697   char buf[1024];
698 
699   if (!fd_is_stream (fd))
700     {
701       g_message ("Socket %d is not stream", fd);
702       return -1;
703     }
704   fp = OVAS_CONNECTION_FROM_FD (fd);
705   kb = plug_get_kb (args);
706   cert = kb_item_get_str (kb, "SSL/cert");
707   key = kb_item_get_str (kb, "SSL/key");
708   passwd = kb_item_get_str (kb, "SSL/password");
709   cafile = kb_item_get_str (kb, "SSL/CA");
710   snprintf (buf, sizeof (buf), "Host/SNI/%d/force_disable", fp->port);
711   if (kb_item_get_int (kb, buf) <= 0)
712     hostname = plug_get_host_fqdn (args);
713 
714   fp->transport = transport;
715   fp->priority = NULL;
716   if (open_SSL_connection (fp, cert, key, passwd, cafile, hostname) <= 0)
717     {
718       g_free (hostname);
719       g_free (cert);
720       g_free (key);
721       g_free (passwd);
722       g_free (cafile);
723       g_message ("Function socket_negotiate_ssl called from %s: "
724                  "SSL/TLS connection failed.",
725                  nasl_get_plugin_filename ());
726       release_connection_fd (fd, 0);
727       return -1;
728     }
729   g_free (hostname);
730   g_free (cert);
731   g_free (key);
732   g_free (passwd);
733   g_free (cafile);
734   return fd;
735 }
736 
737 /*
738  * @brief Get the peer's certificate from an SSL/TLS encapsulated connection.
739  *
740  * @param[in]   fd      Socket file descriptor.
741  * @param[out]  cert    Memory pointer to fill cert pointer.
742  * @param[out]  certlen Size of cert.
743  */
744 void
socket_get_cert(int fd,void ** cert,int * certlen)745 socket_get_cert (int fd, void **cert, int *certlen)
746 {
747   gnutls_session_t session;
748   const gnutls_datum_t *cert_list;
749   unsigned int cert_list_len = 0;
750 
751   if (!cert || !certlen)
752     return;
753   if (!fd_is_stream (fd))
754     {
755       g_message ("Socket %d is not stream", fd);
756       return;
757     }
758   session = ovas_get_tlssession_from_connection (fd);
759   if (!session)
760     {
761       g_message ("Socket %d is not SSL/TLS encapsulated", fd);
762       return;
763     }
764   if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509)
765     return;
766   cert_list = gnutls_certificate_get_peers (session, &cert_list_len);
767   if (cert_list_len == 0)
768     return;
769   *certlen = cert_list[0].size;
770   *cert = g_memdup (cert_list[0].data, *certlen);
771 }
772 
773 /*
774  * @brief Get the TLS version of a connection.
775  *
776  * @param[in]   fd  Socket file descriptor.
777  *
778  * @return OPENVAS_ENCAPS value if valid session and success, -1 if error.
779  */
780 int
socket_get_ssl_version(int fd)781 socket_get_ssl_version (int fd)
782 {
783   gnutls_session_t session;
784   gnutls_protocol_t version;
785 
786   if (!fd_is_stream (fd))
787     {
788       g_message ("Socket %d is not stream", fd);
789       return -1;
790     }
791   session = ovas_get_tlssession_from_connection (fd);
792   if (!session)
793     {
794       g_message ("Socket %d is not SSL/TLS encapsulated", fd);
795       return -1;
796     }
797 
798   version = gnutls_protocol_get_version (session);
799   switch (version)
800     {
801     case GNUTLS_SSL3:
802       return OPENVAS_ENCAPS_SSLv3;
803     case GNUTLS_TLS1:
804       return OPENVAS_ENCAPS_TLSv1;
805     case GNUTLS_TLS1_1:
806       return OPENVAS_ENCAPS_TLSv11;
807     case GNUTLS_TLS1_2:
808       return OPENVAS_ENCAPS_TLSv12;
809     case GNUTLS_TLS1_3:
810       return OPENVAS_ENCAPS_TLSv13;
811     default:
812       return -1;
813     }
814 }
815 
816 /*
817  * @brief Get the session ID from an SSL/TLS encapsulated connection.
818  *
819  * @param[in]   fd      Socket file descriptor.
820  * @param[out]  sid     Pointer where to store Session ID pointer.
821  * @param[out]  ssize   Size of session id buffer.
822  */
823 void
socket_get_ssl_session_id(int fd,void ** sid,size_t * ssize)824 socket_get_ssl_session_id (int fd, void **sid, size_t *ssize)
825 {
826   gnutls_session_t session;
827   void *tmp;
828   *ssize = GNUTLS_MAX_SESSION_ID;
829   int ret;
830 
831   if (!sid)
832     return;
833   if (!fd_is_stream (fd))
834     {
835       g_message ("Socket %d is not stream", fd);
836       return;
837     }
838   session = ovas_get_tlssession_from_connection (fd);
839   if (!session)
840     {
841       g_message ("Socket %d is not SSL/TLS encapsulated", fd);
842       return;
843     }
844   tmp = g_malloc0 (*ssize);
845   ret = gnutls_session_get_id (session, tmp, ssize);
846   if (ret == GNUTLS_E_SUCCESS)
847     *sid = tmp;
848   else
849     {
850       g_free (tmp);
851       *ssize = 0;
852       tlserror ("gnutls_session_id", ret);
853     }
854 }
855 
856 /*
857  * @brief Get the cipher suite used by a SSL/TLS connection.
858  *
859  * @param[in]   fd  Socket file descriptor.
860  *
861  * @return Cipher Suite ID, -1 if error.
862  */
863 int
socket_get_ssl_ciphersuite(int fd)864 socket_get_ssl_ciphersuite (int fd)
865 {
866   gnutls_session_t session;
867   gnutls_kx_algorithm_t kx, kx2;
868   gnutls_cipher_algorithm_t cipher, cipher2;
869   gnutls_mac_algorithm_t mac, mac2;
870   size_t idx = 0;
871   unsigned char cs_id[2];
872 
873   if (!fd_is_stream (fd))
874     {
875       g_message ("Socket %d is not stream", fd);
876       return -1;
877     }
878   session = ovas_get_tlssession_from_connection (fd);
879   if (!session)
880     {
881       g_message ("Socket %d is not SSL/TLS encapsulated", fd);
882       return -1;
883     }
884 
885   kx = gnutls_kx_get (session);
886   cipher = gnutls_cipher_get (session);
887   mac = gnutls_mac_get (session);
888   while (
889     gnutls_cipher_suite_info (idx, (void *) cs_id, &kx2, &cipher2, &mac2, NULL))
890     {
891       if (kx == kx2 && cipher == cipher2 && mac == mac2)
892         return cs_id[0] + cs_id[1];
893       idx++;
894     }
895   return -1;
896 }
897 
898 /* Extended version of open_stream_connection to allow passing a
899    priority string.
900 
901    ABI_BREAK_NOTE: Merge this with open_stream_connection.  */
902 int
open_stream_connection_ext(struct script_infos * args,unsigned int port,int transport,int timeout,const char * priority)903 open_stream_connection_ext (struct script_infos *args, unsigned int port,
904                             int transport, int timeout, const char *priority)
905 {
906   int fd;
907   openvas_connection *fp;
908   char *cert = NULL;
909   char *key = NULL;
910   char *passwd = NULL;
911   char *cafile = NULL;
912   char *hostname = NULL;
913   char *hostname_aux = NULL;
914 
915   /* Because plug_get_host_fqdn() forks for each vhost, we fork() before
916      creating the socket */
917   hostname_aux = plug_get_host_fqdn (args);
918 
919   if (!priority)
920     priority = ""; /* To us an empty string is equivalent to NULL.  */
921 
922   g_debug ("[%d] open_stream_connection: TCP:%d transport:%d timeout:%d "
923            " priority: '%s'",
924            getpid (), port, transport, timeout, priority);
925 
926   if (timeout == -2)
927     timeout = TIMEOUT;
928 
929   switch (transport)
930     {
931     case OPENVAS_ENCAPS_IP:
932 
933     case OPENVAS_ENCAPS_SSLv23:
934     case OPENVAS_ENCAPS_SSLv3:
935     case OPENVAS_ENCAPS_TLSv1:
936     case OPENVAS_ENCAPS_TLSv11:
937     case OPENVAS_ENCAPS_TLSv12:
938     case OPENVAS_ENCAPS_TLSv13:
939     case OPENVAS_ENCAPS_TLScustom:
940     case OPENVAS_ENCAPS_SSLv2:
941       break;
942 
943     default:
944       g_message ("open_stream_connection_ext(): unsupported transport"
945                  " layer %d passed by %s",
946                  transport, args->name);
947       errno = EINVAL;
948 
949       g_free (hostname_aux);
950       return -1;
951     }
952 
953   if ((fd = get_connection_fd ()) < 0)
954     {
955       g_free (hostname_aux);
956       return -1;
957     }
958   fp = OVAS_CONNECTION_FROM_FD (fd);
959 
960   fp->transport = transport;
961   g_free (fp->priority);
962   if (*priority)
963     fp->priority = g_strdup (priority);
964   else
965     fp->priority = NULL;
966   fp->timeout = timeout;
967   fp->port = port;
968   fp->last_err = 0;
969 
970   fp->fd = open_sock_tcp (args, port, timeout);
971   if (fp->fd < 0)
972     goto failed;
973 
974   kb_t kb = plug_get_kb (args);
975   switch (transport)
976     {
977       int ret;
978       char buf[1024];
979 
980     case OPENVAS_ENCAPS_IP:
981       break;
982     case OPENVAS_ENCAPS_SSLv23:
983     case OPENVAS_ENCAPS_SSLv3:
984     case OPENVAS_ENCAPS_TLSv1:
985     case OPENVAS_ENCAPS_TLSv11:
986     case OPENVAS_ENCAPS_TLSv12:
987     case OPENVAS_ENCAPS_TLSv13:
988     case OPENVAS_ENCAPS_TLScustom:
989       cert = kb_item_get_str (kb, "SSL/cert");
990       key = kb_item_get_str (kb, "SSL/key");
991       passwd = kb_item_get_str (kb, "SSL/password");
992 
993       cafile = kb_item_get_str (kb, "SSL/CA");
994 
995       /* fall through */
996 
997     case OPENVAS_ENCAPS_SSLv2:
998       /* We do not need a client certificate in this case */
999       snprintf (buf, sizeof (buf), "Host/SNI/%d/force_disable", fp->port);
1000       if (kb_item_get_int (kb, buf) <= 0)
1001         hostname = hostname_aux;
1002 
1003       ret = open_SSL_connection (fp, cert, key, passwd, cafile, hostname);
1004       g_free (cert);
1005       g_free (key);
1006       g_free (passwd);
1007       g_free (cafile);
1008       if (ret <= 0)
1009         goto failed;
1010       break;
1011     }
1012 
1013   g_free (hostname_aux);
1014 
1015   return fd;
1016 
1017 failed:
1018   release_connection_fd (fd, 0);
1019   return -1;
1020 }
1021 
1022 int
open_stream_connection(struct script_infos * args,unsigned int port,int transport,int timeout)1023 open_stream_connection (struct script_infos *args, unsigned int port,
1024                         int transport, int timeout)
1025 {
1026   return open_stream_connection_ext (args, port, transport, timeout,
1027                                      "NORMAL:+ARCFOUR-128:%COMPAT");
1028 }
1029 
1030 /* Same as open_stream_auto_encaps but allows to force auto detection
1031    of the protocols if FORCE is true.  */
1032 int
open_stream_auto_encaps_ext(struct script_infos * args,unsigned int port,int timeout,int force)1033 open_stream_auto_encaps_ext (struct script_infos *args, unsigned int port,
1034                              int timeout, int force)
1035 {
1036   int fd, transport;
1037 
1038   if (force)
1039     {
1040       /* Try SSL/TLS first */
1041       transport = OPENVAS_ENCAPS_TLScustom;
1042       fd = open_stream_connection (args, port, transport, timeout);
1043       if (fd < 0)
1044         {
1045           transport = OPENVAS_ENCAPS_IP;
1046           fd = open_stream_connection (args, port, OPENVAS_ENCAPS_IP, timeout);
1047           if (fd < 0)
1048             return -1;
1049         }
1050       /* Store that encapsulation mode in the KB.  */
1051       plug_set_port_transport (args, port, transport);
1052       return fd;
1053     }
1054   else
1055     {
1056       transport = plug_get_port_transport (args, port);
1057       fd = open_stream_connection (args, port, transport, timeout);
1058       return fd;
1059     }
1060   /*NOTREACHED*/
1061 }
1062 
1063 int
stream_set_timeout(int fd,int timeout)1064 stream_set_timeout (int fd, int timeout)
1065 {
1066   int old;
1067   openvas_connection *fp;
1068   if (!OPENVAS_STREAM (fd))
1069     {
1070       errno = EINVAL;
1071       return 0;
1072     }
1073   fp = OVAS_CONNECTION_FROM_FD (fd);
1074   old = fp->timeout;
1075   fp->timeout = timeout;
1076   return old;
1077 }
1078 
1079 static int
read_stream_connection_unbuffered(int fd,void * buf0,int min_len,int max_len)1080 read_stream_connection_unbuffered (int fd, void *buf0, int min_len, int max_len)
1081 {
1082   int ret, realfd, trp, t, select_status;
1083   int total = 0, flag = 0, timeout = TIMEOUT, waitall = 0;
1084   unsigned char *buf = (unsigned char *) buf0;
1085   openvas_connection *fp = NULL;
1086   fd_set fdr, fdw;
1087   struct timeval tv;
1088   time_t now, then;
1089 
1090   if (OPENVAS_STREAM (fd))
1091     {
1092       fp = OVAS_CONNECTION_FROM_FD (fd);
1093       trp = fp->transport;
1094       realfd = fp->fd;
1095       fp->last_err = 0;
1096       if (fp->timeout != -2)
1097         timeout = fp->timeout;
1098     }
1099   else
1100     {
1101       trp = OPENVAS_ENCAPS_IP;
1102       if (fd < 0 || fd > 1024)
1103         {
1104           errno = EBADF;
1105           return -1;
1106         }
1107       realfd = fd;
1108     }
1109 
1110 #ifndef INCR_TIMEOUT
1111 #define INCR_TIMEOUT 1
1112 #endif
1113 
1114   if (min_len == max_len || timeout <= 0)
1115     waitall = MSG_WAITALL;
1116   if (trp == OPENVAS_ENCAPS_IP)
1117     {
1118       for (t = 0; total < max_len && (timeout <= 0 || t < timeout);)
1119         {
1120           tv.tv_sec = INCR_TIMEOUT; /* Not timeout! */
1121           tv.tv_usec = 0;
1122           FD_ZERO (&fdr);
1123           FD_SET (realfd, &fdr);
1124           if (select (realfd + 1, &fdr, NULL, NULL, timeout > 0 ? &tv : NULL)
1125               <= 0)
1126             {
1127               t += INCR_TIMEOUT;
1128               /* Try to be smart */
1129               if (total > 0 && flag)
1130                 return total;
1131               else if (total >= min_len)
1132                 flag++;
1133             }
1134           else
1135             {
1136               errno = 0;
1137               ret = recv (realfd, buf + total, max_len - total, waitall);
1138               if (ret < 0)
1139                 if (errno != EINTR)
1140                   {
1141                     return total;
1142                   }
1143                 else
1144                   ret = 0;
1145               else if (ret == 0) /* EOF */
1146                 {
1147                   return total;
1148                 }
1149               /*ret > 0 */
1150               total += ret;
1151               if (min_len > 0 && total >= min_len)
1152                 return total;
1153               flag = 0;
1154             }
1155         }
1156       return total;
1157     }
1158 
1159   switch (trp)
1160     {
1161       /* OPENVAS_ENCAPS_IP was treated before with the non-OpenVAS fd */
1162     case OPENVAS_ENCAPS_SSLv2:
1163     case OPENVAS_ENCAPS_SSLv23:
1164     case OPENVAS_ENCAPS_SSLv3:
1165     case OPENVAS_ENCAPS_TLSv1:
1166     case OPENVAS_ENCAPS_TLSv11:
1167     case OPENVAS_ENCAPS_TLSv12:
1168     case OPENVAS_ENCAPS_TLSv13:
1169     case OPENVAS_ENCAPS_TLScustom:
1170       if (getpid () != fp->pid)
1171         {
1172           g_debug ("PID %d tries to use a SSL/TLS connection established "
1173                    "by PID %d\n",
1174                    getpid (), fp->pid);
1175           errno = EINVAL;
1176           return -1;
1177         }
1178 
1179       then = time (NULL);
1180       for (t = 0; timeout <= 0 || t < timeout; t = now - then)
1181         {
1182           now = time (NULL);
1183           tv.tv_sec = INCR_TIMEOUT;
1184           tv.tv_usec = 0;
1185           FD_ZERO (&fdr);
1186           FD_ZERO (&fdw);
1187           FD_SET (realfd, &fdr);
1188           FD_SET (realfd, &fdw);
1189 
1190           select_status = select (realfd + 1, &fdr, &fdw, NULL, &tv);
1191 
1192           if (select_status > 0)
1193             {
1194               /* TLS FIXME: handle rehandshake */
1195               ret = gnutls_record_recv (fp->tls_session, buf + total,
1196                                         max_len - total);
1197               if (ret > 0)
1198                 {
1199                   total += ret;
1200                   if (total >= max_len)
1201                     return total;
1202                 }
1203               else if (ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN)
1204                 {
1205                   /* This branch also handles the case where ret == 0,
1206                    * i.e. that the connection has been closed.  This is
1207                    * for compatibility with the old OpenSSL based openvas
1208                    * code which treated SSL_ERROR_ZERO_RETURN as an
1209                    * error too.
1210                    */
1211                   if (ret < 0)
1212                     pid_perror ("gnutls_record_recv");
1213                   else
1214                     g_debug ("gnutls_record_recv[%d]: EOF\n", getpid ());
1215                   fp->last_err = EPIPE;
1216                   return total;
1217                 }
1218             }
1219 
1220           if (min_len > 0 && total >= min_len)
1221             return total;
1222         }
1223       if (t >= timeout)
1224         fp->last_err = ETIMEDOUT;
1225       return total;
1226 
1227     default:
1228       if (fp->transport || fp->fd != 0)
1229         g_message ("Function %s (calling internal function %s) called from %s: "
1230                    "Severe bug! Unhandled transport layer %d (fd=%d).",
1231                    nasl_get_function_name () ?: "script_main_function",
1232                    __func__, nasl_get_plugin_filename (), fp->transport, fd);
1233       else
1234         g_message ("read_stream_connection_unbuffered: "
1235                    "fd=%d is closed",
1236                    fd);
1237       errno = EINVAL;
1238       return -1;
1239     }
1240   /*NOTREACHED*/
1241 }
1242 
1243 int
read_stream_connection_min(int fd,void * buf0,int min_len,int max_len)1244 read_stream_connection_min (int fd, void *buf0, int min_len, int max_len)
1245 {
1246   openvas_connection *fp;
1247 
1248   if (OPENVAS_STREAM (fd))
1249     {
1250       fp = OVAS_CONNECTION_FROM_FD (fd);
1251       if (fp->buf != NULL)
1252         {
1253           int l1, l2;
1254 
1255           if (max_len == 1)
1256             min_len = 1; /* avoid "magic read" later */
1257           l2 = max_len > fp->bufcnt ? fp->bufcnt : max_len;
1258           if (l2 > 0)
1259             {
1260               memcpy (buf0, fp->buf + fp->bufptr, l2);
1261               fp->bufcnt -= l2;
1262               if (fp->bufcnt == 0)
1263                 {
1264                   fp->bufptr = 0;
1265                   fp->buf[0] = '\0'; /* debug */
1266                 }
1267               else
1268                 fp->bufptr += l2;
1269               if (l2 >= min_len || l2 >= max_len)
1270                 return l2;
1271               max_len -= l2;
1272               min_len -= l2;
1273             }
1274           if (min_len > fp->bufsz)
1275             {
1276               l1 = read_stream_connection_unbuffered (fd, (char *) buf0 + l2,
1277                                                       min_len, max_len);
1278               if (l1 > 0)
1279                 return l1 + l2;
1280               else
1281                 return l2;
1282             }
1283           /* Fill buffer */
1284           l1 =
1285             read_stream_connection_unbuffered (fd, fp->buf, min_len, fp->bufsz);
1286           if (l1 <= 0)
1287             return l2;
1288 
1289           fp->bufcnt = l1;
1290           l1 = max_len > fp->bufcnt ? fp->bufcnt : max_len;
1291           memcpy ((char *) buf0 + l2, fp->buf + fp->bufptr, l1);
1292           fp->bufcnt -= l1;
1293           if (fp->bufcnt == 0)
1294             fp->bufptr = 0;
1295           else
1296             fp->bufptr += l1;
1297           return l1 + l2;
1298         }
1299     }
1300   return read_stream_connection_unbuffered (fd, buf0, min_len, max_len);
1301 }
1302 
1303 int
read_stream_connection(int fd,void * buf0,int len)1304 read_stream_connection (int fd, void *buf0, int len)
1305 {
1306   return read_stream_connection_min (fd, buf0, -1, len);
1307 }
1308 
1309 static int
write_stream_connection4(int fd,void * buf0,int n,int i_opt)1310 write_stream_connection4 (int fd, void *buf0, int n, int i_opt)
1311 {
1312   int ret, count;
1313   unsigned char *buf = (unsigned char *) buf0;
1314   openvas_connection *fp;
1315   fd_set fdr, fdw;
1316   struct timeval tv;
1317   int e;
1318 
1319   if (!OPENVAS_STREAM (fd))
1320     {
1321       g_debug ("write_stream_connection: fd <%d> invalid\n", fd);
1322       errno = EINVAL;
1323       return -1;
1324     }
1325 
1326   fp = OVAS_CONNECTION_FROM_FD (fd);
1327   fp->last_err = 0;
1328 
1329   switch (fp->transport)
1330     {
1331     case OPENVAS_ENCAPS_IP:
1332       for (count = 0; count < n;)
1333         {
1334           ret = send (fp->fd, buf + count, n - count, i_opt);
1335 
1336           if (ret <= 0)
1337             {
1338               if (ret < 0)
1339                 fp->last_err = errno;
1340               else
1341                 fp->last_err = EPIPE;
1342               break;
1343             }
1344 
1345           count += ret;
1346         }
1347       break;
1348 
1349     case OPENVAS_ENCAPS_SSLv2:
1350     case OPENVAS_ENCAPS_SSLv23:
1351     case OPENVAS_ENCAPS_SSLv3:
1352     case OPENVAS_ENCAPS_TLSv1:
1353     case OPENVAS_ENCAPS_TLSv11:
1354     case OPENVAS_ENCAPS_TLSv12:
1355     case OPENVAS_ENCAPS_TLSv13:
1356     case OPENVAS_ENCAPS_TLScustom:
1357 
1358       /* i_opt ignored for SSL */
1359       for (count = 0; count < n;)
1360         {
1361           ret = gnutls_record_send (fp->tls_session, buf + count, n - count);
1362 
1363           if (ret > 0)
1364             {
1365               count += ret;
1366             }
1367           else if (ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN)
1368             {
1369               /* This branch also handles the case where ret == 0,
1370                * i.e. that the connection has been closed.  This is
1371                * for compatibility with the old openvas code which
1372                * treated SSL_ERROR_ZERO_RETURN as an error too.
1373                */
1374               if (ret < 0)
1375                 pid_perror ("gnutls_record_send");
1376               else
1377                 g_debug ("gnutls_record_send[%d]: EOF\n", getpid ());
1378               fp->last_err = EPIPE;
1379               break;
1380             }
1381 
1382           if (fp->timeout >= 0)
1383             tv.tv_sec = fp->timeout;
1384           else
1385             tv.tv_sec = TIMEOUT;
1386           tv.tv_usec = 0;
1387 
1388           do
1389             {
1390               errno = 0;
1391               FD_ZERO (&fdr);
1392               FD_ZERO (&fdw);
1393               FD_SET (fp->fd, &fdr);
1394               FD_SET (fp->fd, &fdw);
1395               e = select (fp->fd + 1, &fdr, &fdw, NULL, &tv);
1396             }
1397           while (e < 0 && errno == EINTR);
1398 
1399           if (e <= 0)
1400             {
1401               pid_perror ("select");
1402               fp->last_err = ETIMEDOUT;
1403               break;
1404             }
1405         }
1406       break;
1407 
1408     default:
1409       if (fp->transport || fp->fd != 0)
1410         g_message ("Function %s (calling internal function %s) called from %s: "
1411                    "Severe bug! Unhandled transport layer %d (fd=%d).",
1412                    nasl_get_function_name () ?: "script_main_function",
1413                    __func__, nasl_get_plugin_filename (), fp->transport, fd);
1414       else
1415         g_message ("read_stream_connection_unbuffered: fd=%d is "
1416                    "closed",
1417                    fd);
1418       errno = EINVAL;
1419       return -1;
1420     }
1421 
1422   if (count == 0 && n > 0)
1423     return -1;
1424   else
1425     return count;
1426 }
1427 
1428 int
write_stream_connection(int fd,void * buf0,int n)1429 write_stream_connection (int fd, void *buf0, int n)
1430 {
1431   return write_stream_connection4 (fd, buf0, n, 0);
1432 }
1433 
1434 int
nsend(int fd,void * data,int length,int i_opt)1435 nsend (int fd, void *data, int length, int i_opt)
1436 {
1437   int n = 0;
1438 
1439   if (OPENVAS_STREAM (fd))
1440     {
1441       if (connections[fd - OPENVAS_FD_OFF].fd < 0)
1442         g_message ("OpenVAS file descriptor %d closed ?!", fd);
1443       else
1444         return write_stream_connection4 (fd, data, length, i_opt);
1445     }
1446   /* Trying OS's send() */
1447   block_socket (fd); /* ??? */
1448   do
1449     {
1450       struct timeval tv = {0, 5};
1451       fd_set wr;
1452       int e;
1453 
1454       FD_ZERO (&wr);
1455       FD_SET (fd, &wr);
1456 
1457       errno = 0;
1458       e = select (fd + 1, NULL, &wr, NULL, &tv);
1459       if (e > 0)
1460         n = os_send (fd, data, length, i_opt);
1461       else if (e < 0 && errno == EINTR)
1462         continue;
1463       else
1464         break;
1465     }
1466   while (n <= 0 && errno == EINTR);
1467   if (n < 0)
1468     g_message ("[%d] nsend():send %s", getpid (), strerror (errno));
1469 
1470   return n;
1471 }
1472 
1473 int
nrecv(int fd,void * data,int length,int i_opt)1474 nrecv (int fd, void *data, int length, int i_opt)
1475 {
1476   int e;
1477   if (OPENVAS_STREAM (fd))
1478     {
1479       if (connections[fd - OPENVAS_FD_OFF].fd < 0)
1480         g_message ("OpenVAS file descriptor %d closed ?!", fd);
1481       else
1482         return read_stream_connection (fd, data, length);
1483     }
1484   /* Trying OS's recv()
1485    *
1486    * Do *NOT* use os_recv() here, as it will be blocking until the exact
1487    * amount of requested data arrives
1488    */
1489   block_socket (fd);
1490   do
1491     {
1492       e = recv (fd, data, length, i_opt);
1493     }
1494   while (e < 0 && errno == EINTR);
1495   return e;
1496 }
1497 
1498 /**
1499  * @brief Register a hook function for close_stream_connection.
1500  *
1501  * The function adds the given hook function to the list of hooks to
1502  * be run by close_stream_connection.  These hooks are intended to
1503  * test whether they need to close the stream them self.  See argument
1504  * to the hook function is the file descriptor of the stream.  The
1505  * hook shall return 0 if it has taken over control of that file
1506  * descriptor.  The same function is only aded once to the list of
1507  * hooks.
1508  *
1509  * @param fnc  The hook function.  See above for details.
1510  */
1511 void
add_close_stream_connection_hook(int (* fnc)(int fd))1512 add_close_stream_connection_hook (int (*fnc) (int fd))
1513 {
1514   struct csc_hook_s *hook;
1515 
1516   for (hook = csc_hooks; hook; hook = hook->next)
1517     if (hook->fnc == fnc)
1518       return; /* Already added.  */
1519 
1520   hook = g_malloc0 (sizeof *hook);
1521   hook->fnc = fnc;
1522   hook->next = csc_hooks;
1523   csc_hooks = hook;
1524 }
1525 
1526 /**
1527  * @brief Run the hooks for close_stream_connection.
1528  *
1529  * The function runs all registered hooks until the first hook returns
1530  * with zero to indicate that it has taken over control of the socket.
1531  * Further hooks are then not anymore run because the file descriptor
1532  * is not anymore valid.
1533  *
1534  * @param fd The file descriptor of the stream.
1535 
1536  * @return Zero if one of the hooks has closed the connection;
1537  *         non-zero otherwise.
1538  */
1539 static int
run_csc_hooks(int fd)1540 run_csc_hooks (int fd)
1541 {
1542   struct csc_hook_s *hook;
1543 
1544   for (hook = csc_hooks; hook; hook = hook->next)
1545     if (hook->fnc && !hook->fnc (fd))
1546       return 0;
1547   return -1;
1548 }
1549 
1550 int
close_stream_connection(int fd)1551 close_stream_connection (int fd)
1552 {
1553   openvas_connection *fp;
1554   if (!OPENVAS_STREAM (fd))
1555     {
1556       errno = EINVAL;
1557       return -1;
1558     }
1559   fp = OVAS_CONNECTION_FROM_FD (fd);
1560   g_debug ("close_stream_connection TCP:%d (fd=%d)", fp->port, fd);
1561 
1562   if (!OPENVAS_STREAM (fd)) /* Will never happen if debug is on! */
1563     {
1564       if (fd < 0 || fd > 1024)
1565         {
1566           errno = EINVAL;
1567           return -1;
1568         }
1569       shutdown (fd, 2);
1570       return socket_close (fd);
1571     }
1572   if (!run_csc_hooks (fd))
1573     return release_connection_fd (fd, 1);
1574   else
1575     return release_connection_fd (fd, 0);
1576 }
1577 
1578 const char *
get_encaps_name(openvas_encaps_t code)1579 get_encaps_name (openvas_encaps_t code)
1580 {
1581   static char str[100];
1582   switch (code)
1583     {
1584     case OPENVAS_ENCAPS_AUTO:
1585       return "auto";
1586     case OPENVAS_ENCAPS_IP:
1587       return "IP";
1588     case OPENVAS_ENCAPS_SSLv2:
1589       return "SSLv2";
1590     case OPENVAS_ENCAPS_SSLv23:
1591       return "SSLv23";
1592     case OPENVAS_ENCAPS_SSLv3:
1593       return "SSLv3";
1594     case OPENVAS_ENCAPS_TLSv1:
1595       return "TLSv1";
1596     case OPENVAS_ENCAPS_TLSv11:
1597       return "TLSv11";
1598     case OPENVAS_ENCAPS_TLSv12:
1599       return "TLSv12";
1600     case OPENVAS_ENCAPS_TLSv13:
1601       return "TLSv13";
1602     case OPENVAS_ENCAPS_TLScustom:
1603       return "TLScustom";
1604     default:
1605       snprintf (str, sizeof (str), "[unknown transport layer - code %d (0x%x)]",
1606                 code, code);
1607       return str;
1608     }
1609 }
1610 
1611 const char *
get_encaps_through(openvas_encaps_t code)1612 get_encaps_through (openvas_encaps_t code)
1613 {
1614   static char str[100];
1615   switch (code)
1616     {
1617     case OPENVAS_ENCAPS_IP:
1618       return "";
1619     case OPENVAS_ENCAPS_SSLv2:
1620     case OPENVAS_ENCAPS_SSLv23:
1621     case OPENVAS_ENCAPS_SSLv3:
1622     case OPENVAS_ENCAPS_TLSv1:
1623     case OPENVAS_ENCAPS_TLSv11:
1624     case OPENVAS_ENCAPS_TLSv12:
1625     case OPENVAS_ENCAPS_TLSv13:
1626     case OPENVAS_ENCAPS_TLScustom:
1627       return " through SSL";
1628     default:
1629       snprintf (str, sizeof (str),
1630                 " through unknown transport layer - code %d (0x%x)", code,
1631                 code);
1632       return str;
1633     }
1634 }
1635 
1636 static int
open_socket(struct sockaddr * paddr,int type,int protocol,int timeout,int len)1637 open_socket (struct sockaddr *paddr, int type, int protocol, int timeout,
1638              int len)
1639 {
1640   fd_set fd_w;
1641   struct timeval to;
1642   int soc, x;
1643   int opt;
1644   unsigned int opt_sz;
1645   int family;
1646 
1647   __port_closed = 0;
1648 
1649   if (paddr->sa_family == AF_INET)
1650     {
1651       family = AF_INET;
1652       if ((soc = socket (AF_INET, type, protocol)) < 0)
1653         {
1654           pid_perror ("socket");
1655           return -1;
1656         }
1657     }
1658   else
1659     {
1660       family = AF_INET6;
1661       if ((soc = socket (AF_INET6, type, protocol)) < 0)
1662         {
1663           pid_perror ("socket");
1664           return -1;
1665         }
1666     }
1667 
1668   if (timeout == -2)
1669     timeout = TIMEOUT;
1670 
1671   if (timeout > 0)
1672     if (unblock_socket (soc) < 0)
1673       {
1674         close (soc);
1675         return -1;
1676       }
1677 
1678   gvm_source_set_socket (soc, 0, family);
1679 
1680   if (connect (soc, paddr, len) < 0)
1681     {
1682       pid_perror ("connect");
1683     again:
1684       switch (errno)
1685         {
1686         case EINPROGRESS:
1687         case EAGAIN:
1688           FD_ZERO (&fd_w);
1689           FD_SET (soc, &fd_w);
1690           to.tv_sec = timeout;
1691           to.tv_usec = 0;
1692           x = select (soc + 1, NULL, &fd_w, NULL, &to);
1693           if (x == 0)
1694             {
1695               pid_perror ("connect->select: timeout");
1696               socket_close (soc);
1697               errno = ETIMEDOUT;
1698               return -1;
1699             }
1700           else if (x < 0)
1701             {
1702               if (errno == EINTR)
1703                 {
1704                   errno = EAGAIN;
1705                   goto again;
1706                 }
1707               pid_perror ("select");
1708               socket_close (soc);
1709               return -1;
1710             }
1711 
1712           opt = 0;
1713           opt_sz = sizeof (opt);
1714           if (getsockopt (soc, SOL_SOCKET, SO_ERROR, &opt, &opt_sz) < 0)
1715             {
1716               pid_perror ("getsockopt");
1717               socket_close (soc);
1718               return -1;
1719             }
1720           if (opt == 0)
1721             break;
1722           errno = opt;
1723           pid_perror ("SO_ERROR");
1724           /* fallthrough */
1725         default:
1726           __port_closed = 1;
1727           socket_close (soc);
1728           return -1;
1729         }
1730     }
1731   block_socket (soc);
1732   return soc;
1733 }
1734 
1735 int
open_sock_opt_hn(const char * hostname,unsigned int port,int type,int protocol,int timeout)1736 open_sock_opt_hn (const char *hostname, unsigned int port, int type,
1737                   int protocol, int timeout)
1738 {
1739   struct sockaddr_in addr;
1740   struct sockaddr_in6 addr6;
1741   struct in6_addr in6addr;
1742 
1743   gvm_resolve_as_addr6 (hostname, &in6addr);
1744   if (IN6_IS_ADDR_V4MAPPED (&in6addr))
1745     {
1746       bzero ((void *) &addr, sizeof (addr));
1747       addr.sin_family = AF_INET;
1748       addr.sin_port = htons ((unsigned short) port);
1749       addr.sin_addr.s_addr = in6addr.s6_addr32[3];
1750       return open_socket ((struct sockaddr *) &addr, type, protocol, timeout,
1751                           sizeof (struct sockaddr_in));
1752     }
1753   else
1754     {
1755       bzero ((void *) &addr6, sizeof (addr6));
1756       addr6.sin6_family = AF_INET6;
1757       addr6.sin6_port = htons ((unsigned short) port);
1758       memcpy (&addr6.sin6_addr, &in6addr, sizeof (struct in6_addr));
1759       return open_socket ((struct sockaddr *) &addr6, type, protocol, timeout,
1760                           sizeof (struct sockaddr_in6));
1761     }
1762 }
1763 
1764 int
open_sock_tcp(struct script_infos * args,unsigned int port,int timeout)1765 open_sock_tcp (struct script_infos *args, unsigned int port, int timeout)
1766 {
1767   int ret, retry = 0;
1768   const char *timeout_retry;
1769 
1770   timeout_retry = prefs_get ("timeout_retry");
1771   if (timeout_retry)
1772     retry = atoi (timeout_retry);
1773   if (retry < 0)
1774     retry = 0;
1775 
1776   while (retry >= 0)
1777     {
1778       errno = 0;
1779       ret = open_sock_option (args, port, SOCK_STREAM, IPPROTO_TCP, timeout);
1780       if (ret >= 0 || errno != ETIMEDOUT)
1781         break;
1782       retry--;
1783     }
1784   if (ret < 0 && errno == ETIMEDOUT)
1785     {
1786       int log_count, attempts = 0;
1787       char *ip_str = plug_get_host_ip_str (args), buffer[1024];
1788       kb_t kb = plug_get_kb (args);
1789       const char *max_attempts;
1790 
1791       max_attempts = prefs_get ("open_sock_max_attempts");
1792       if (max_attempts)
1793         attempts = atoi (max_attempts);
1794       if (attempts < 0)
1795         attempts = 0;
1796 
1797       g_snprintf (buffer, sizeof (buffer), "ConnectTimeout/%s/%d", ip_str,
1798                   port);
1799       log_count = kb_item_get_int (kb, buffer);
1800       if (log_count == -1)
1801         log_count = 0;
1802       if (log_count < 3)
1803         {
1804           g_message ("open_sock_tcp: %s:%d time-out.", ip_str, port);
1805           log_count++;
1806           kb_item_set_int (kb, buffer, log_count);
1807         }
1808       if ((log_count >= attempts) && (attempts != 0))
1809         {
1810           /* After some unsuccessfully attempts, the port is set to closed to
1811            * avoid new attempts from other plugins.
1812            */
1813           if (host_get_port_state (args, port) > 0)
1814             {
1815               char ip_str[INET6_ADDRSTRLEN];
1816 
1817               g_snprintf (buffer, sizeof (buffer), "Ports/tcp/%d", port);
1818               g_message ("open_sock_tcp: %s:%d too many timeouts. "
1819                          "This port will be set to closed.",
1820                          ip_str, port);
1821               kb_item_set_int (kb, buffer, 0);
1822 
1823               addr6_to_str (args->ip, ip_str);
1824               snprintf (
1825                 buffer, sizeof (buffer),
1826                 "ERRMSG|||%s|||%s|||%d/tcp||| |||Too many timeouts. The port"
1827                 " was set to closed.",
1828                 ip_str, plug_current_vhost () ?: " ", port);
1829               kb_item_push_str (args->results, "internal/results", buffer);
1830             }
1831         }
1832       g_free (ip_str);
1833     }
1834 
1835   return ret;
1836 }
1837 
1838 int
open_sock_option(struct script_infos * args,unsigned int port,int type,int protocol,int timeout)1839 open_sock_option (struct script_infos *args, unsigned int port, int type,
1840                   int protocol, int timeout)
1841 {
1842   struct sockaddr_in addr;
1843   struct sockaddr_in6 addr6;
1844   struct in6_addr *t;
1845 
1846   t = plug_get_host_ip (args);
1847   if (!t)
1848     {
1849       g_message ("ERROR ! NO ADDRESS ASSOCIATED WITH NAME");
1850       return (-1);
1851     }
1852   if (IN6_ARE_ADDR_EQUAL (t, &in6addr_any))
1853     return (-1);
1854   if (IN6_IS_ADDR_V4MAPPED (t))
1855     {
1856       bzero ((void *) &addr, sizeof (addr));
1857       addr.sin_family = AF_INET;
1858       addr.sin_port = htons ((unsigned short) port);
1859       addr.sin_addr.s_addr = t->s6_addr32[3];
1860       return open_socket ((struct sockaddr *) &addr, type, protocol, timeout,
1861                           sizeof (struct sockaddr_in));
1862     }
1863   else
1864     {
1865       bzero ((void *) &addr6, sizeof (addr6));
1866       addr6.sin6_family = AF_INET6;
1867       addr6.sin6_port = htons ((unsigned short) port);
1868       memcpy (&addr6.sin6_addr, t, sizeof (struct in6_addr));
1869       return open_socket ((struct sockaddr *) &addr6, type, protocol, timeout,
1870                           sizeof (struct sockaddr_in6));
1871     }
1872 }
1873 
1874 /**
1875  * @brief Reads a text from the socket stream into the argument buffer, always
1876  * @brief appending a '\\0' byte.
1877  *
1878  * @param buf  Buffer to read into.
1879  *
1880  * @return Number of bytes read, without the trailing '\\0'.
1881  */
1882 int
recv_line(int soc,char * buf,size_t bufsiz)1883 recv_line (int soc, char *buf, size_t bufsiz)
1884 {
1885   int n;
1886   unsigned int ret = 0;
1887 
1888   /* Dirty SSL hack */
1889   if (OPENVAS_STREAM (soc))
1890     {
1891       unsigned int ret = 0;
1892       buf[0] = '\0';
1893 
1894       do
1895         {
1896           n = read_stream_connection_min (soc, buf + ret, 1, 1);
1897           switch (n)
1898             {
1899             case -1:
1900               if (ret == 0)
1901                 return -1;
1902               else
1903                 return ret;
1904               break;
1905 
1906             case 0:
1907               return ret;
1908               break;
1909 
1910             default:
1911               ret++;
1912             }
1913         }
1914       while (buf[ret - 1] != '\0' && buf[ret - 1] != '\n' && ret < bufsiz);
1915 
1916       if (ret > 0)
1917         {
1918           if (buf[ret - 1] != '\0')
1919             {
1920               if (ret < bufsiz)
1921                 buf[ret] = '\0';
1922               else
1923                 buf[bufsiz - 1] = '\0';
1924             }
1925         }
1926 
1927       return ret;
1928     }
1929   else
1930     {
1931       fd_set rd;
1932 
1933       do
1934         {
1935           int e;
1936         again:
1937           errno = 0;
1938           FD_ZERO (&rd);
1939           FD_SET (soc, &rd);
1940           e = select (soc + 1, &rd, NULL, NULL, NULL);
1941           if (e == 0 && !FD_ISSET (soc, &rd))
1942             return -1;
1943           if (e < 0 && errno == EINTR)
1944             goto again;
1945           if (e > 0)
1946             {
1947               n = recv (soc, buf + ret, 1, 0);
1948               switch (n)
1949                 {
1950                 case -1:
1951                   if (errno == EINTR)
1952                     continue;
1953                   if (ret == 0)
1954                     return -1;
1955                   else
1956                     return ret;
1957                   break;
1958                 case 0:
1959                   return ret;
1960                   break;
1961                 default:
1962                   ret++;
1963                 }
1964             }
1965           else
1966             break;
1967         }
1968       while (buf[ret - 1] != '\0' && buf[ret - 1] != '\n' && ret < bufsiz);
1969 
1970       if (ret > 0)
1971         {
1972           if (buf[ret - 1] != '\0')
1973             {
1974               if (ret < bufsiz)
1975                 buf[ret] = '\0';
1976               else
1977                 buf[bufsiz - 1] = '\0';
1978             }
1979         }
1980     }
1981 
1982   return ret;
1983 }
1984 
1985 int
socket_close(int soc)1986 socket_close (int soc)
1987 {
1988   return close (soc);
1989 }
1990 
1991 /*
1992  * Select() routines
1993  */
1994 
1995 int
fd_is_stream(int fd)1996 fd_is_stream (int fd)
1997 {
1998   return OPENVAS_STREAM (fd); /* Should probably be smarter... */
1999 }
2000 
2001 int
stream_get_buffer_sz(int fd)2002 stream_get_buffer_sz (int fd)
2003 {
2004   openvas_connection *p;
2005   if (!OPENVAS_STREAM (fd))
2006     return -1;
2007   p = OVAS_CONNECTION_FROM_FD (fd);
2008   return p->bufsz;
2009 }
2010 
2011 int
stream_set_buffer(int fd,int sz)2012 stream_set_buffer (int fd, int sz)
2013 {
2014   openvas_connection *p;
2015   char *b;
2016 
2017   if (!OPENVAS_STREAM (fd))
2018     return -1;
2019 
2020   p = OVAS_CONNECTION_FROM_FD (fd);
2021   if (sz < p->bufcnt)
2022     return -1; /* Do not want to lose data */
2023 
2024   if (sz == 0)
2025     {
2026       g_free (p->buf);
2027       p->buf = NULL;
2028       p->bufsz = 0;
2029       return 0;
2030     }
2031   else if (p->buf == 0)
2032     {
2033       p->buf = g_malloc0 (sz);
2034       if (p->buf == NULL)
2035         return -1;
2036       p->bufsz = sz;
2037       p->bufptr = 0;
2038       p->bufcnt = 0;
2039       return 0;
2040     }
2041   else
2042     {
2043       if (p->bufcnt > 0)
2044         {
2045           memmove (p->buf, p->buf + p->bufptr, p->bufcnt);
2046           p->bufptr = 0;
2047         }
2048       b = g_realloc (p->buf, sz);
2049       if (b == NULL)
2050         return -1;
2051       p->buf = b;
2052       p->bufsz = sz;
2053       return 0;
2054     }
2055 }
2056 
2057 /*------------------------------------------------------------------*/
2058 
2059 int
os_send(int soc,void * buf,int len,int opt)2060 os_send (int soc, void *buf, int len, int opt)
2061 {
2062   char *buf0 = (char *) buf;
2063   int e, n;
2064   for (n = 0; n < len;)
2065     {
2066       errno = 0;
2067       e = send (soc, buf0 + n, len - n, opt);
2068       if (e < 0 && errno == EINTR)
2069         continue;
2070       else if (e <= 0)
2071         return -1;
2072       else
2073         n += e;
2074     }
2075   return n;
2076 }
2077 
2078 int
os_recv(int soc,void * buf,int len,int opt)2079 os_recv (int soc, void *buf, int len, int opt)
2080 {
2081   char *buf0 = (char *) buf;
2082   int e, n;
2083   for (n = 0; n < len;)
2084     {
2085       errno = 0;
2086       e = recv (soc, buf0 + n, len - n, opt);
2087       if (e < 0 && errno == EINTR)
2088         continue;
2089       else if (e <= 0)
2090         return -1;
2091       else
2092         n += e;
2093     }
2094   return n;
2095 }
2096 
2097 /* This is a helper function for nasl_get_sock_info.  It is used to
2098    retrieve information about SOCK.  */
2099 int
get_sock_infos(int sock,int * r_transport,void ** r_tls_session)2100 get_sock_infos (int sock, int *r_transport, void **r_tls_session)
2101 {
2102   openvas_connection *fp;
2103 
2104   if (!OPENVAS_STREAM (sock))
2105     return ENOTSOCK;
2106   fp = &(connections[sock - OPENVAS_FD_OFF]);
2107 
2108   *r_transport = fp->transport;
2109   *r_tls_session = fp->tls_session;
2110   return 0;
2111 }
2112 
2113 /*
2114  * 0 is considered as the biggest number, since it
2115  * ends our string
2116  */
2117 static int
qsort_compar(const void * a,const void * b)2118 qsort_compar (const void *a, const void *b)
2119 {
2120   u_short *aa = (u_short *) a;
2121   u_short *bb = (u_short *) b;
2122   if (*aa == 0)
2123     return (1);
2124   else if (*bb == 0)
2125     return (-1);
2126   else
2127     return (*aa - *bb);
2128 }
2129 
2130 /**
2131  * @brief Converts a string like "-100,200-1024,3000-4000,60000-" into an array
2132  * @brief of port numbers
2133  *
2134  * This function is (c) Fyodor <fyodor@dhp.com> and was taken from
2135  * his excellent and outstanding scanner Nmap
2136  * See http://www.insecure.org/nmap/ for details about
2137  * Nmap
2138  */
2139 unsigned short *
getpts(char * origexpr,int * len)2140 getpts (char *origexpr, int *len)
2141 {
2142   int exlen;
2143   char *p, *q;
2144   unsigned short *tmp, *ports;
2145   int i = 0, j = 0, start, end;
2146   char *expr;
2147   char *mem;
2148   char *s_start, *s_end;
2149   static unsigned short *last_ret = NULL;
2150   static char *last_expr = NULL;
2151   static int last_num;
2152 
2153   expr = g_strdup (origexpr);
2154   exlen = strlen (origexpr);
2155   mem = expr;
2156 
2157   if (last_expr != NULL)
2158     {
2159       if (strcmp (last_expr, expr) == 0)
2160         {
2161           if (len != NULL)
2162             *len = last_num;
2163           g_free (mem);
2164           return last_ret;
2165         }
2166       else
2167         {
2168           g_free (last_expr);
2169           last_expr = NULL;
2170           g_free (&last_ret);
2171           last_ret = NULL;
2172         }
2173     }
2174 
2175   ports = g_malloc0 (65536 * sizeof (short));
2176   for (; j < exlen; j++)
2177     if (expr[j] != ' ')
2178       expr[i++] = expr[j];
2179   expr[i] = '\0';
2180 
2181   if ((s_start = strstr (expr, "T:")) != NULL)
2182     expr = &(s_start[2]);
2183 
2184   if ((s_end = strstr (expr, "U:")) != NULL)
2185     {
2186       if (s_end[-1] == ',')
2187         s_end--;
2188       s_end[0] = '\0';
2189     }
2190 
2191   i = 0;
2192   while ((p = strchr (expr, ',')))
2193     {
2194       *p = '\0';
2195       if (*expr == '-')
2196         {
2197           start = 1;
2198           end = atoi (expr + 1);
2199         }
2200       else
2201         {
2202           start = end = atoi (expr);
2203           if ((q = strchr (expr, '-')) && *(q + 1))
2204             end = atoi (q + 1);
2205           else if (q && !*(q + 1))
2206             end = 65535;
2207         }
2208       if (start < 1)
2209         start = 1;
2210       if (start > end)
2211         {
2212           g_free (mem);
2213           g_free (ports);
2214           return NULL;
2215         }
2216       for (j = start; j <= end; j++)
2217         ports[i++] = j;
2218       expr = p + 1;
2219     }
2220   if (*expr == '-')
2221     {
2222       start = 1;
2223       end = atoi (expr + 1);
2224     }
2225   else
2226     {
2227       start = end = atoi (expr);
2228       if ((q = strchr (expr, '-')) && *(q + 1))
2229         end = atoi (q + 1);
2230       else if (q && !*(q + 1))
2231         end = 65535;
2232     }
2233   if (start < 1)
2234     start = 1;
2235   if (start > end)
2236     {
2237       g_free (mem);
2238       g_free (ports);
2239       return NULL;
2240     }
2241   for (j = start; j <= end; j++)
2242     ports[i++] = j;
2243   ports[i++] = 0;
2244 
2245   qsort (ports, i, sizeof (u_short), qsort_compar);
2246   tmp = g_realloc (ports, i * sizeof (short));
2247   if (len != NULL)
2248     *len = i - 1;
2249   g_free (mem);
2250 
2251   last_ret = tmp;
2252   last_expr = g_strdup (origexpr);
2253   last_num = i - 1;
2254   return tmp;
2255 }
2256