summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/appl/kx/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/appl/kx/common.c')
-rw-r--r--crypto/heimdal/appl/kx/common.c812
1 files changed, 0 insertions, 812 deletions
diff --git a/crypto/heimdal/appl/kx/common.c b/crypto/heimdal/appl/kx/common.c
deleted file mode 100644
index 223c6bb..0000000
--- a/crypto/heimdal/appl/kx/common.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "kx.h"
-
-RCSID("$Id: common.c,v 1.66 2002/08/22 16:23:28 joda Exp $");
-
-char x_socket[MaxPathLen];
-
-u_int32_t display_num;
-char display[MaxPathLen];
-int display_size = sizeof(display);
-char xauthfile[MaxPathLen];
-int xauthfile_size = sizeof(xauthfile);
-u_char cookie[16];
-size_t cookie_len = sizeof(cookie);
-
-#ifndef X_UNIX_PATH
-#define X_UNIX_PATH "/tmp/.X11-unix/X"
-#endif
-
-#ifndef X_PIPE_PATH
-#define X_PIPE_PATH "/tmp/.X11-pipe/X"
-#endif
-
-/*
- * Allocate a unix domain socket in `s' for display `dpy' and with
- * filename `pattern'
- *
- * 0 if all is OK
- * -1 if bind failed badly
- * 1 if dpy is already used */
-
-static int
-try_socket (struct x_socket *s, int dpy, const char *pattern)
-{
- struct sockaddr_un addr;
- int fd;
-
- fd = socket (AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0)
- err (1, "socket AF_UNIX");
- memset (&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- snprintf (addr.sun_path, sizeof(addr.sun_path), pattern, dpy);
- if(bind(fd,
- (struct sockaddr *)&addr,
- sizeof(addr)) < 0) {
- close (fd);
- if (errno == EADDRINUSE ||
- errno == EACCES /* Cray return EACCESS */
-#ifdef ENOTUNIQ
- || errno == ENOTUNIQ /* bug in Solaris 2.4 */
-#endif
- )
- return 1;
- else
- return -1;
- }
- s->fd = fd;
- s->pathname = strdup (addr.sun_path);
- if (s->pathname == NULL)
- errx (1, "strdup: out of memory");
- s->flags = UNIX_SOCKET;
- return 0;
-}
-
-#ifdef MAY_HAVE_X11_PIPES
-/*
- * Allocate a stream (masqueraded as a named pipe)
- *
- * 0 if all is OK
- * -1 if bind failed badly
- * 1 if dpy is already used
- */
-
-static int
-try_pipe (struct x_socket *s, int dpy, const char *pattern)
-{
- char path[MAXPATHLEN];
- int ret;
- int fd;
- int pipefd[2];
-
- snprintf (path, sizeof(path), pattern, dpy);
- fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (fd < 0) {
- if (errno == EEXIST)
- return 1;
- else
- return -1;
- }
-
- close (fd);
-
- ret = pipe (pipefd);
- if (ret < 0)
- err (1, "pipe");
-
- ret = ioctl (pipefd[1], I_PUSH, "connld");
- if (ret < 0) {
- if(errno == ENOSYS)
- return -1;
- err (1, "ioctl I_PUSH");
- }
-
- ret = fattach (pipefd[1], path);
- if (ret < 0)
- err (1, "fattach %s", path);
-
- s->fd = pipefd[0];
- close (pipefd[1]);
- s->pathname = strdup (path);
- if (s->pathname == NULL)
- errx (1, "strdup: out of memory");
- s->flags = STREAM_PIPE;
- return 0;
-}
-#endif /* MAY_HAVE_X11_PIPES */
-
-/*
- * Try to create a TCP socket in `s' corresponding to display `dpy'.
- *
- * 0 if all is OK
- * -1 if bind failed badly
- * 1 if dpy is already used
- */
-
-static int
-try_tcp (struct x_socket *s, int dpy)
-{
- struct sockaddr_in tcpaddr;
- struct in_addr local;
- int one = 1;
- int fd;
-
- memset(&local, 0, sizeof(local));
- local.s_addr = htonl(INADDR_LOOPBACK);
-
- fd = socket (AF_INET, SOCK_STREAM, 0);
- if (fd < 0)
- err (1, "socket AF_INET");
-#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
- setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&one,
- sizeof(one));
-#endif
- memset (&tcpaddr, 0, sizeof(tcpaddr));
- tcpaddr.sin_family = AF_INET;
- tcpaddr.sin_addr = local;
- tcpaddr.sin_port = htons(6000 + dpy);
- if (bind (fd, (struct sockaddr *)&tcpaddr,
- sizeof(tcpaddr)) < 0) {
- close (fd);
- if (errno == EADDRINUSE)
- return 1;
- else
- return -1;
- }
- s->fd = fd;
- s->pathname = NULL;
- s->flags = TCP;
- return 0;
-}
-
-/*
- * The potential places to create unix sockets.
- */
-
-static char *x_sockets[] = {
-X_UNIX_PATH "%u",
-"/var/X/.X11-unix/X" "%u",
-"/usr/spool/sockets/X11/" "%u",
-NULL
-};
-
-/*
- * Dito for stream pipes.
- */
-
-#ifdef MAY_HAVE_X11_PIPES
-static char *x_pipes[] = {
-X_PIPE_PATH "%u",
-"/var/X/.X11-pipe/X" "%u",
-NULL
-};
-#endif
-
-/*
- * Create the directory corresponding to dirname of `path' or fail.
- */
-
-static void
-try_mkdir (const char *path)
-{
- char *dir;
- char *p;
- int oldmask;
-
- if((dir = strdup (path)) == NULL)
- errx (1, "strdup: out of memory");
- p = strrchr (dir, '/');
- if (p)
- *p = '\0';
-
- oldmask = umask(0);
- mkdir (dir, 01777);
- umask (oldmask);
- free (dir);
-}
-
-/*
- * Allocate a display, returning the number of sockets in `number' and
- * all the corresponding sockets in `sockets'. If `tcp_socket' is
- * true, also allcoaet a TCP socket.
- *
- * The return value is the display allocated or -1 if an error occurred.
- */
-
-int
-get_xsockets (int *number, struct x_socket **sockets, int tcp_socket)
-{
- int dpy;
- struct x_socket *s;
- int n;
- int i;
-
- s = malloc (sizeof(*s) * 5);
- if (s == NULL)
- errx (1, "malloc: out of memory");
-
- try_mkdir (X_UNIX_PATH);
- try_mkdir (X_PIPE_PATH);
-
- for(dpy = 4; dpy < 256; ++dpy) {
- char **path;
- int tmp = 0;
-
- n = 0;
- for (path = x_sockets; *path; ++path) {
- tmp = try_socket (&s[n], dpy, *path);
- if (tmp == -1) {
- if (errno != ENOTDIR && errno != ENOENT)
- return -1;
- } else if (tmp == 1) {
- while(--n >= 0) {
- close (s[n].fd);
- free (s[n].pathname);
- }
- break;
- } else if (tmp == 0)
- ++n;
- }
- if (tmp == 1)
- continue;
-
-#ifdef MAY_HAVE_X11_PIPES
- for (path = x_pipes; *path; ++path) {
- tmp = try_pipe (&s[n], dpy, *path);
- if (tmp == -1) {
- if (errno != ENOTDIR && errno != ENOENT && errno != ENOSYS)
- return -1;
- } else if (tmp == 1) {
- while (--n >= 0) {
- close (s[n].fd);
- free (s[n].pathname);
- }
- break;
- } else if (tmp == 0)
- ++n;
- }
-
- if (tmp == 1)
- continue;
-#endif
-
- if (tcp_socket) {
- tmp = try_tcp (&s[n], dpy);
- if (tmp == -1)
- return -1;
- else if (tmp == 1) {
- while (--n >= 0) {
- close (s[n].fd);
- free (s[n].pathname);
- }
- break;
- } else if (tmp == 0)
- ++n;
- }
- break;
- }
- if (dpy == 256)
- errx (1, "no free x-servers");
- for (i = 0; i < n; ++i)
- if (s[i].flags & LISTENP
- && listen (s[i].fd, SOMAXCONN) < 0)
- err (1, "listen %s", s[i].pathname ? s[i].pathname : "tcp");
- *number = n;
- *sockets = s;
- return dpy;
-}
-
-/*
- * Change owner on the `n' sockets in `sockets' to `uid', `gid'.
- * Return 0 is succesful or -1 if an error occurred.
- */
-
-int
-chown_xsockets (int n, struct x_socket *sockets, uid_t uid, gid_t gid)
-{
- int i;
-
- for (i = 0; i < n; ++i)
- if (sockets[i].pathname != NULL)
- if (chown (sockets[i].pathname, uid, gid) < 0)
- return -1;
- return 0;
-}
-
-/*
- * Connect to local display `dnr' with local transport or TCP.
- * Return a file descriptor.
- */
-
-int
-connect_local_xsocket (unsigned dnr)
-{
- int fd;
- char **path;
-
- for (path = x_sockets; *path; ++path) {
- struct sockaddr_un addr;
-
- fd = socket (AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0)
- break;
- memset (&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- snprintf (addr.sun_path, sizeof(addr.sun_path), *path, dnr);
- if (connect (fd, (struct sockaddr *)&addr, sizeof(addr)) == 0)
- return fd;
- close(fd);
- }
- {
- struct sockaddr_in addr;
-
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd < 0)
- err (1, "socket AF_INET");
- memset (&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr.sin_port = htons(6000 + dnr);
- if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0)
- return fd;
- close(fd);
- }
- err (1, "connecting to local display %u", dnr);
-}
-
-/*
- * Create a cookie file with a random cookie for the localhost. The
- * file name will be stored in `xauthfile' (but not larger than
- * `xauthfile_size'), and the cookie returned in `cookie', `cookie_sz'.
- * Return 0 if succesful, or errno.
- */
-
-int
-create_and_write_cookie (char *xauthfile,
- size_t xauthfile_size,
- u_char *cookie,
- size_t cookie_sz)
-{
- Xauth auth;
- char tmp[64];
- int fd;
- FILE *f;
- char hostname[MaxHostNameLen];
- struct in_addr loopback;
- int saved_errno;
-
- gethostname (hostname, sizeof(hostname));
- loopback.s_addr = htonl(INADDR_LOOPBACK);
-
- auth.family = FamilyLocal;
- auth.address = hostname;
- auth.address_length = strlen(auth.address);
- snprintf (tmp, sizeof(tmp), "%d", display_num);
- auth.number_length = strlen(tmp);
- auth.number = tmp;
- auth.name = COOKIE_TYPE;
- auth.name_length = strlen(auth.name);
- auth.data_length = cookie_sz;
- auth.data = (char*)cookie;
-#ifdef KRB5
- krb5_generate_random_block (cookie, cookie_sz);
-#else
- krb_generate_random_block (cookie, cookie_sz);
-#endif
-
- strlcpy(xauthfile, "/tmp/AXXXXXX", xauthfile_size);
- fd = mkstemp(xauthfile);
- if(fd < 0) {
- saved_errno = errno;
- syslog(LOG_ERR, "create_and_write_cookie: mkstemp: %m");
- return saved_errno;
- }
- f = fdopen(fd, "r+");
- if(f == NULL){
- saved_errno = errno;
- close(fd);
- return errno;
- }
- if(XauWriteAuth(f, &auth) == 0) {
- saved_errno = errno;
- fclose(f);
- return saved_errno;
- }
-
- /*
- * I would like to write a cookie for localhost:n here, but some
- * stupid code in libX11 will not look for cookies of that type,
- * so we are forced to use FamilyWild instead.
- */
-
- auth.family = FamilyWild;
- auth.address_length = 0;
-
-#if 0 /* XXX */
- auth.address = (char *)&loopback;
- auth.address_length = sizeof(loopback);
-#endif
-
- if (XauWriteAuth(f, &auth) == 0) {
- saved_errno = errno;
- fclose (f);
- return saved_errno;
- }
-
- if(fclose(f))
- return errno;
- return 0;
-}
-
-/*
- * Verify and remove cookies. Read and parse a X-connection from
- * `fd'. Check the cookie used is the same as in `cookie'. Remove the
- * cookie and copy the rest of it to `sock'.
- * Expect cookies iff cookiesp.
- * Return 0 iff ok.
- *
- * The protocol is as follows:
- *
- * C->S: [Bl] 1
- * unused 1
- * protocol major version 2
- * protocol minor version 2
- * length of auth protocol name(n) 2
- * length of auth protocol data 2
- * unused 2
- * authorization protocol name n
- * pad pad(n)
- * authorization protocol data d
- * pad pad(d)
- *
- * S->C: Failed
- * 0 1
- * length of reason 1
- * protocol major version 2
- * protocol minor version 2
- * length in 4 bytes unit of
- * additional data (n+p)/4 2
- * reason n
- * unused p = pad(n)
- */
-
-int
-verify_and_remove_cookies (int fd, int sock, int cookiesp)
-{
- u_char beg[12];
- int bigendianp;
- unsigned n, d, npad, dpad;
- char *protocol_name, *protocol_data;
- u_char zeros[6] = {0, 0, 0, 0, 0, 0};
- u_char refused[20] = {0, 10,
- 0, 0, /* protocol major version */
- 0, 0, /* protocol minor version */
- 0, 0, /* length of additional data / 4 */
- 'b', 'a', 'd', ' ', 'c', 'o', 'o', 'k', 'i', 'e',
- 0, 0};
-
- if (net_read (fd, beg, sizeof(beg)) != sizeof(beg))
- return 1;
- if (net_write (sock, beg, 6) != 6)
- return 1;
- bigendianp = beg[0] == 'B';
- if (bigendianp) {
- n = (beg[6] << 8) | beg[7];
- d = (beg[8] << 8) | beg[9];
- } else {
- n = (beg[7] << 8) | beg[6];
- d = (beg[9] << 8) | beg[8];
- }
- npad = (4 - (n % 4)) % 4;
- dpad = (4 - (d % 4)) % 4;
- protocol_name = malloc(n + npad);
- if (n + npad != 0 && protocol_name == NULL)
- return 1;
- protocol_data = malloc(d + dpad);
- if (d + dpad != 0 && protocol_data == NULL) {
- free (protocol_name);
- return 1;
- }
- if (net_read (fd, protocol_name, n + npad) != n + npad)
- goto fail;
- if (net_read (fd, protocol_data, d + dpad) != d + dpad)
- goto fail;
- if (cookiesp) {
- if (strncmp (protocol_name, COOKIE_TYPE, strlen(COOKIE_TYPE)) != 0)
- goto refused;
- if (d != cookie_len ||
- memcmp (protocol_data, cookie, cookie_len) != 0)
- goto refused;
- }
- free (protocol_name);
- free (protocol_data);
- if (net_write (sock, zeros, 6) != 6)
- return 1;
- return 0;
-refused:
- refused[2] = beg[2];
- refused[3] = beg[3];
- refused[4] = beg[4];
- refused[5] = beg[5];
- if (bigendianp)
- refused[7] = 3;
- else
- refused[6] = 3;
-
- net_write (fd, refused, sizeof(refused));
-fail:
- free (protocol_name);
- free (protocol_data);
- return 1;
-}
-
-/*
- * Return 0 iff `cookie' is compatible with the cookie for the
- * localhost with name given in `ai' (or `hostname') and display
- * number in `disp_nr'.
- */
-
-static int
-match_local_auth (Xauth* auth,
- struct addrinfo *ai, const char *hostname, int disp_nr)
-{
- int auth_disp;
- char *tmp_disp;
- struct addrinfo *a;
-
- tmp_disp = malloc(auth->number_length + 1);
- if (tmp_disp == NULL)
- return -1;
- memcpy(tmp_disp, auth->number, auth->number_length);
- tmp_disp[auth->number_length] = '\0';
- auth_disp = atoi(tmp_disp);
- free (tmp_disp);
- if (auth_disp != disp_nr)
- return 1;
- for (a = ai; a != NULL; a = a->ai_next) {
- if ((auth->family == FamilyLocal
- || auth->family == FamilyWild)
- && a->ai_canonname != NULL
- && strncmp (auth->address,
- a->ai_canonname,
- auth->address_length) == 0)
- return 0;
- }
- if (hostname != NULL
- && (auth->family == FamilyLocal
- || auth->family == FamilyWild)
- && strncmp (auth->address, hostname, auth->address_length) == 0)
- return 0;
- return 1;
-}
-
-/*
- * Find `our' cookie from the cookie file `f' and return it or NULL.
- */
-
-static Xauth*
-find_auth_cookie (FILE *f)
-{
- Xauth *ret = NULL;
- char local_hostname[MaxHostNameLen];
- char *display = getenv("DISPLAY");
- char d[MaxHostNameLen + 4];
- char *colon;
- struct addrinfo *ai;
- struct addrinfo hints;
- int disp;
- int error;
-
- if(display == NULL)
- display = ":0";
- strlcpy(d, display, sizeof(d));
- display = d;
- colon = strchr (display, ':');
- if (colon == NULL)
- disp = 0;
- else {
- *colon = '\0';
- disp = atoi (colon + 1);
- }
- if (strcmp (display, "") == 0
- || strncmp (display, "unix", 4) == 0
- || strncmp (display, "localhost", 9) == 0) {
- gethostname (local_hostname, sizeof(local_hostname));
- display = local_hostname;
- }
- memset (&hints, 0, sizeof(hints));
- hints.ai_flags = AI_CANONNAME;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- error = getaddrinfo (display, NULL, &hints, &ai);
- if (error)
- ai = NULL;
-
- for (; (ret = XauReadAuth (f)) != NULL; XauDisposeAuth(ret)) {
- if (match_local_auth (ret, ai, display, disp) == 0) {
- if (ai != NULL)
- freeaddrinfo (ai);
- return ret;
- }
- }
- if (ai != NULL)
- freeaddrinfo (ai);
- return NULL;
-}
-
-/*
- * Get rid of the cookie that we were sent and get the correct one
- * from our own cookie file instead.
- */
-
-int
-replace_cookie(int xserver, int fd, char *filename, int cookiesp) /* XXX */
-{
- u_char beg[12];
- int bigendianp;
- unsigned n, d, npad, dpad;
- FILE *f;
- u_char zeros[6] = {0, 0, 0, 0, 0, 0};
-
- if (net_read (fd, beg, sizeof(beg)) != sizeof(beg))
- return 1;
- if (net_write (xserver, beg, 6) != 6)
- return 1;
- bigendianp = beg[0] == 'B';
- if (bigendianp) {
- n = (beg[6] << 8) | beg[7];
- d = (beg[8] << 8) | beg[9];
- } else {
- n = (beg[7] << 8) | beg[6];
- d = (beg[9] << 8) | beg[8];
- }
- if (n != 0 || d != 0)
- return 1;
- f = fopen(filename, "r");
- if (f != NULL) {
- Xauth *auth = find_auth_cookie (f);
- u_char len[6] = {0, 0, 0, 0, 0, 0};
-
- fclose (f);
-
- if (auth != NULL) {
- n = auth->name_length;
- d = auth->data_length;
- } else {
- n = 0;
- d = 0;
- }
- if (bigendianp) {
- len[0] = n >> 8;
- len[1] = n & 0xFF;
- len[2] = d >> 8;
- len[3] = d & 0xFF;
- } else {
- len[0] = n & 0xFF;
- len[1] = n >> 8;
- len[2] = d & 0xFF;
- len[3] = d >> 8;
- }
- if (net_write (xserver, len, 6) != 6) {
- XauDisposeAuth(auth);
- return 1;
- }
- if(n != 0 && net_write (xserver, auth->name, n) != n) {
- XauDisposeAuth(auth);
- return 1;
- }
- npad = (4 - (n % 4)) % 4;
- if (npad && net_write (xserver, zeros, npad) != npad) {
- XauDisposeAuth(auth);
- return 1;
- }
- if (d != 0 && net_write (xserver, auth->data, d) != d) {
- XauDisposeAuth(auth);
- return 1;
- }
- XauDisposeAuth(auth);
- dpad = (4 - (d % 4)) % 4;
- if (dpad && net_write (xserver, zeros, dpad) != dpad)
- return 1;
- } else {
- if(net_write(xserver, zeros, 6) != 6)
- return 1;
- }
- return 0;
-}
-
-/*
- * Some simple controls on the address and corresponding socket
- */
-
-int
-suspicious_address (int sock, struct sockaddr_in addr)
-{
- char data[40];
- socklen_t len = sizeof(data);
-
- return addr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-#if defined(IP_OPTIONS) && defined(HAVE_GETSOCKOPT)
- || getsockopt (sock, IPPROTO_IP, IP_OPTIONS, data, &len) < 0
- || len != 0
-#endif
- ;
-}
-
-/*
- * This really sucks, but these functions are used and if we're not
- * linking against libkrb they don't exist. Using the heimdal storage
- * functions will not work either cause we do not always link with
- * libkrb5 either.
- */
-
-#ifndef KRB4
-
-int
-krb_get_int(void *f, u_int32_t *to, int size, int lsb)
-{
- int i;
- unsigned char *from = (unsigned char *)f;
-
- *to = 0;
- if(lsb){
- for(i = size-1; i >= 0; i--)
- *to = (*to << 8) | from[i];
- }else{
- for(i = 0; i < size; i++)
- *to = (*to << 8) | from[i];
- }
- return size;
-}
-
-int
-krb_put_int(u_int32_t from, void *to, size_t rem, int size)
-{
- int i;
- unsigned char *p = (unsigned char *)to;
-
- if (rem < size)
- return -1;
-
- for(i = size - 1; i >= 0; i--){
- p[i] = from & 0xff;
- from >>= 8;
- }
- return size;
-}
-
-#endif /* !KRB4 */
OpenPOWER on IntegriCloud