CR 7121230 Rad unix transport paths should be created under /system/volatile/rad/
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
#
import socket
import ssl
import getpass
import subprocess
import os
import rad.client as rad
import rad.adaptor as adapt
#
# Default path for authenticated AF_UNIX socket
#
_RAD_PATH_AFUNIX_AUTH = "/system/volatile/rad/radsocket"
#
# Make pipes quack enough like a socket to satisfy RecordMarkingSocket
#
class SocketLike(object):
def __init__(self, process):
self._process = process
self._in = process.stdin
self._out = process.stdout
def recv(self, n):
#
# If the file is unbuffered, it reads one byte at a time.
# If the file is buffered, it waits until all n bytes are
# read before returning.
# Neither is acceptable, so we use os.read.
#
return os.read(self._out.fileno(), n)
def sendall(self, buf):
r = self._in.write(buf)
self._in.flush()
return r
def close(self):
#
# We would prefer to simply close our end of the pipe
# and let rad die on its own, but reaching in and doing
# that to a pipe inside a subprocess might defy its
# expectations. Instead we terminate the subprocess.
#
self._process.terminate()
#
# Map a path given the specified root directory
#
def map_path(root, path):
if root != None and path[0] == '/':
return root + path;
return path
#
# Connect to a privately spawned copy of rad
# Defaults to loading all system modules if a list of modules isn't provided
#
def connect_private(modules = None, debug = False, env = None, root = None,
auxargs = None, locale = None):
args = [ map_path(root, "/usr/lib/rad/rad"),
"-M", map_path(root, "/usr/lib/rad/transport/mod_xport_pipe.so"),
"-M", map_path(root, "/usr/lib/rad/protocol/mod_proto_rad.so"),
"-t", "stdin:exit" ]
if modules:
for m in modules:
args.extend([ "-M", map_path(root, m) ])
else:
args.extend([ "-m", map_path(root, "/usr/lib/rad/module") ])
if debug:
args.extend([ "-d" ])
if auxargs:
args.extend(auxargs)
p = subprocess.Popen(args, 0, None, subprocess.PIPE, subprocess.PIPE,
env = env)
return rad.RadConnection(SocketLike(p), locale = locale)
#
# Connect to a remote rad daemon using SSH
# The remote system must have netcat (/usr/bin/nc) installed
#
def connect_ssh(host, user = None, locale = None):
if user:
host = "%s@%s" % (user, host)
p = subprocess.Popen(["/usr/bin/ssh", "-q", "-e", "none",
"-o", "BatchMode yes", host, "/usr/lib/rad/radpipe" ],
0, None, subprocess.PIPE, subprocess.PIPE)
return rad.RadConnection(SocketLike(p), locale = locale)
#
# Connect to the local rad daemon via the standard unix domain socket
#
def connect_local(path = _RAD_PATH_AFUNIX_AUTH, locale = None):
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM);
s.connect(path)
return rad.RadConnection(s, locale = locale)
#
# Connect to a remote rad daemon at the standard port
#
def connect_ssl(host, port = 12302, locale = None):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
s.connect((host, port))
s = ssl.wrap_socket(s)
return rad.RadConnection(s, locale = locale)
#
# Fetches and caches a handle to the authentication object.
# Supplies some convenience routines built on top of it.
#
class RadAuth(object):
AUTH_NAME = rad.Name("org.opensolaris.os.rad",
[("type", "authentication")])
def __init__(self, rc):
self._auth = adapt.Adaptor(rc.get_object(self.AUTH_NAME))
def handle(self):
return self._auth
#
# Perform a terminal-interactive PAM login
# Currently not recommended due to bug in Python's getpass.getpass()
#
def pam_login(self, user = None):
if not user:
user = raw_input("Username: ")
blk = self._auth.login("C", user);
types = self._auth._object.types
BlockType = types.BlockType
MsgType = types.MsgType
while True:
resp = []
if blk.type == BlockType.success:
break
if blk.type == BlockType.error:
raise Exception("Authentication Failed")
for m in blk.messages:
if m.style == MsgType.prompt_echo_off:
r = getpass.getpass(m.message)
resp.append(r)
elif m.style == MsgType.prompt_echo_on:
r = raw_input(m.message)
resp.append(r)
elif m.style == MsgType.text_info:
print m.message
elif m.style == MsgType.error_msg:
print "ERROR: %s" % m.message
blk = self._auth.submit(resp)
self._auth.complete()