rand: use size_t for size argument to RAND_bytes_ex()
[openssl.git] / crypto / rand / rand_egd.c
index 5eb3225b1fc5fc035617250c7547cc3b5fb81a5c..dc1833169c9909fd908d426595425dd0523df8ae 100644 (file)
@@ -1,26 +1,23 @@
 /*
- * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
 #include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_EGD
-NON_EMPTY_TRANSLATION_UNIT
-#else
 
-# include <openssl/crypto.h>
-# include <openssl/e_os2.h>
-# include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <openssl/e_os2.h>
+#include <openssl/rand.h>
 
 /*
  * Query an EGD
  */
 
-# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI)
+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI)
 int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
 {
     return -1;
@@ -36,27 +33,80 @@ int RAND_egd_bytes(const char *path, int bytes)
     return -1;
 }
 
-# else
+#else
 
-#  include <openssl/opensslconf.h>
-#  include OPENSSL_UNISTD
-#  include <stddef.h>
-#  include <sys/types.h>
-#  include <sys/socket.h>
-#  ifndef NO_SYS_UN_H
-#   ifdef OPENSSL_SYS_VXWORKS
-#    include <streams/un.h>
-#   else
-#    include <sys/un.h>
-#   endif
+# include <unistd.h>
+# include <stddef.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# ifndef NO_SYS_UN_H
+#  ifdef OPENSSL_SYS_VXWORKS
+#   include <streams/un.h>
 #  else
+#   include <sys/un.h>
+#  endif
+# else
 struct sockaddr_un {
     short sun_family;           /* AF_UNIX */
     char sun_path[108];         /* path name (gag) */
 };
-#  endif                         /* NO_SYS_UN_H */
-#  include <string.h>
-#  include <errno.h>
+# endif                         /* NO_SYS_UN_H */
+# include <string.h>
+# include <errno.h>
+
+# if defined(OPENSSL_SYS_TANDEM)
+/*
+ * HPNS:
+ *
+ *  Our current MQ 5.3 EGD requies compatability-mode sockets
+ *  This code forces the mode to compatibility if required
+ *  and then restores the mode.
+ *
+ *  Needs review:
+ *
+ *  The better long-term solution is to either run two EGD's each in one of
+ *  the two modes or revise the EGD code to listen on two different sockets
+ *  (each in one of the two modes).
+ */
+_variable
+int hpns_socket(int family,
+                int type,
+                int protocol,
+                char* transport)
+{
+    int  socket_rc;
+    char current_transport[20];
+
+#  define AF_UNIX_PORTABILITY    "$ZAFN2"
+#  define AF_UNIX_COMPATIBILITY  "$ZPLS"
+
+    if (!_arg_present(transport) || transport != NULL || transport[0] == '\0')
+        return socket(family, type, protocol);
+
+    socket_transport_name_get(AF_UNIX, current_transport, 20);
+
+    if (strcmp(current_transport,transport) == 0)
+        return socket(family, type, protocol);
+
+    /* set the requested socket transport */
+    if (socket_transport_name_set(AF_UNIX, transport))
+        return -1;
+
+    socket_rc = socket(family,type,protocol);
+
+    /* set mode back to what it was */
+    if (socket_transport_name_set(AF_UNIX, current_transport))
+        return -1;
+
+    return socket_rc;
+}
+
+/*#define socket(a,b,c,...) hpns_socket(a,b,c,__VA_ARGS__) */
+
+static int hpns_connect_attempt = 0;
+
+# endif /* defined(OPENSSL_SYS_HPNS) */
+
 
 int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
 {
@@ -75,7 +125,11 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
         return -1;
     strcpy(addr.sun_path, path);
     i = offsetof(struct sockaddr_un, sun_path) + strlen(path);
+#if defined(OPENSSL_SYS_TANDEM)
+    fd = hpns_socket(AF_UNIX, SOCK_STREAM, 0, AF_UNIX_COMPATIBILITY);
+#else
     fd = socket(AF_UNIX, SOCK_STREAM, 0);
+#endif
     if (fd == -1 || (fp = fdopen(fd, "r+")) == NULL)
         return -1;
     setbuf(fp, NULL);
@@ -84,26 +138,38 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
     for ( ; ; ) {
         if (connect(fd, (struct sockaddr *)&addr, i) == 0)
             break;
-#  ifdef EISCONN
+# ifdef EISCONN
         if (errno == EISCONN)
             break;
-#  endif
+# endif
         switch (errno) {
-#  ifdef EINTR
+# ifdef EINTR
         case EINTR:
-#  endif
-#  ifdef EAGAIN
+# endif
+# ifdef EAGAIN
         case EAGAIN:
-#  endif
-#  ifdef EINPROGRESS
+# endif
+# ifdef EINPROGRESS
         case EINPROGRESS:
-#  endif
-#  ifdef EALREADY
+# endif
+# ifdef EALREADY
         case EALREADY:
-#  endif
+# endif
             /* No error, try again */
             break;
         default:
+# if defined(OPENSSL_SYS_TANDEM)
+            if (hpns_connect_attempt == 0) {
+                /* try the other kind of AF_UNIX socket */
+                close(fd);
+                fd = hpns_socket(AF_UNIX, SOCK_STREAM, 0, AF_UNIX_PORTABILITY);
+                if (fd == -1)
+                    return -1;
+                ++hpns_connect_attempt;
+                break;  /* try the connect again */
+            }
+# endif
+
             ret = -1;
             goto err;
         }
@@ -154,6 +220,4 @@ int RAND_egd(const char *path)
     return RAND_egd_bytes(path, 255);
 }
 
-# endif
-
 #endif