diff --git a/README/README.AUTH b/README/README.AUTH
new file mode 100644
index 0000000000000000000000000000000000000000..f9ebd86a2178172b0f6867296724ad159c293be3
--- /dev/null
+++ b/README/README.AUTH
@@ -0,0 +1,382 @@
+
+Authentication to rootd/proofd servers
+======================================
+
+The rootd/proofd daemon servers accept 6 methods of authentication, listed 
+in Table 1, together with their internal codes and short names.
+Method 5 (rfio) is provided for fast access when security is not an issue.
+Method 0 can be 'secured' by using a session public key, automatically 
+generated, which allows to avoid direct exchange of passwords; since this
+may slow down the process, it can be switched of if not needed. 
+
+   Table 1: authentication methods available
+  +-------------------------------------------------------------------------+
+  |   Method                |  code  |  short name  |  in .rootrc  | Secure |
+  |-------------------------------------------------------------------------|
+  |   (user,password) clear |   0    |  clear       |  Clear       | No/Yes |
+  |   (user,password) SRP   |   1    |  srp         |  SRP         |  Yes   |
+  |    Kerberos V           |   2    |  krb5        |  Krb5        |  Yes   |
+  |   Globus GSSAPI         |   3    |  globus      |  Globus      |  Yes   |
+  |   SSH                   |   4    |  ssh         |  Ssh         |  Yes   |
+  |   (uid,gid)             |   5    |  rfio        |  Rfio        |  No    |
+  +-------------------------------------------------------------------------+
+
+A specific method can be requested via the .rootrc family files (in order of
+priority $HOME/.rootrc, /etc/root/system.rootrc and
+$ROOTSYS/etc/system.rootrc), the file $HOME/.authrootrc (superseded by the
+variable AUTHROOTRC, if defined), or during the root session as explained
+below.
+
+Controlling access
+==================
+
+Upon request of access, rootd/proofd build a list of secure methods available
+locally; this is based on the compilation flags for SRP, Kerberos and Globus,
+and on the running of the 'sshd' daemon for SSH. By default the two servers
+accept authentications only via the methods in such a list. However the
+administrator of the servers can grant access via other authentication methods
+by defining a host specific list in etc/rpdauth.allow (see the example for this
+file under etc for more details).
+
+Negotiation
+===========
+
+Simple negotiation is supported as follows. The client sends the preferred
+method (the first one in the list, see below) to the server; if this is among
+the methods accepted by the server (not necessarily the one preferred by the
+server) authentication is attempted. In the case the attempt is unsuccessful,
+the server sends back the list of the remaining methods accepted (if any); the
+client compares the server list with its own list of remaining methods and
+makes a new attempt if the overlap of the two lists is not empty; and so on.
+
+Slave/Data servers authentication during a PROOF session
+========================================================
+
+During a PROOF session there is the potential problem of Master/Slave or
+Slave/Data_Server authentication. For slaves, the list of methods to be tried
+is specified in the proof.conf file as a list of methods short names. However,
+before build the corresponding entry in THostAuth (see below) TProof checks
+that the method can be applied, i.e. that there valid credentials. The way
+these are transmitted depends on the method and on the Client/Master
+authentication method.
+
+ * Clear:  to authenticate 'clear' to slaves, the master needs the relevant
+           entry in the .netrc or .rootnetrc files; however, if the
+           client/master authentication was also 'clear', the password is
+           already present on the master process and is used for later clear
+           authentications.
+
+ * SRP:    to authenticate 'SRP' to slaves, the master needs the relevant entry
+           in the .netrc or .rootnetrc files; the syntax is the same as for
+           'clear' authentication with the keyword 'secure' at the place of
+           'machine'
+
+ * Krb5    to authenticate 'Kerberos' to slaves, the master needs the Kerberos
+           tokens; these must be initialized by hand on the master, since for
+           the time being, ticket forwarding has not been implemented.
+
+ * Globus  to authenticate 'Globus' to slaves, the master needs globus
+           credentials; this is possible (and automatic) only if the
+           client/master authentication was also 'globus'
+
+ * SSH     to authenticate 'SSH' to slaves, the master needs the relevant
+           private key files in $HOME/.ssh (on the master).
+
+ * Rfio    to authenticate 'Rfio' to slaves, the user must have the same
+           (uid,gid) on master and slaves.
+
+Negotiation is active also between master and slaves, so it is a good habit to
+ask for rfio first to accelerate as possible the authentication process.
+
+The method actually used is listed by gProof->Print().
+
+If the slaves need to access data servers which are not part of the proof
+cluster, the login info vis-a-vis of these may be specified with the proofdserv
+card in the .authrootrc files (see below and etc/example.authrootrc for
+details); the collected information is then transmitted to all the active
+slaves upon creation.
+
+
+Entries in .rootrc
+==================
+
+The authentication related entries in the .rootrc family of files define
+directives applying to all remote host and all remote accounts. The available
+directives are the following:
+
+* General switchings
+
+   Rootd.Authentication:    <code> Proofd.Authentication   <code>
+
+  These variables specify the default method to be attempted for remote
+  authentication for rootd and proofd respectively; <code> is the internal code
+  given in Table 1; these directives supersede the default ('ssh' for normal
+  users and 'clear' for anonymous users).
+
+* The <method>.Login directives specify the default login for the method:
+
+  Clear.Login, SRP.Login, Ssh.Login, Rfio.Login:   <username>   (e.g.: qwerty)
+  Krb5.Login:    <principal>                       (e.g.: qwerty@THIS.DOM.AIN)
+  Globus.Login:   cd:<dir_with_my_certs> cf:<my_cert_file> \
+                  kf:<my_key_file> ad:<dir_with_CA_certs>
+
+* The <method>.LoginPrompt directives specify whether root should prompt you
+  for the login (with default the login specified via <method>.Login; possible
+  values are 0 or no for no prompt, 1 or yes to have the prompt; valid
+  examples:
+
+  Clear.LoginPrompt:   0
+  Krb5.LoginPrompt:    1
+  Globus.LoginPrompt:  no
+  Ssh.LoginPrompt:     yes
+
+  Default is no prompt.
+
+  For anonymous 'clear' login, setting off the Login.Prompt implies automatic
+  generation of the password in the form <user>@<local_host_fqdn>, where <user>
+  is obtained from the variable USER or from ' getpwuid(getuid())->pw_name '.
+
+* The <method>.ReUse directives specify whether root reuse valid authentication
+  once established; possible values are '0' or 'no' for OFF, '1' or 'yes' for ON.
+  When this option is active, the client generates a session RSA key pair and 
+  transmits the public key to the server; the server generates a session 'token' 
+  which can be used by the client for later access to the server. 
+  This facility is implemented for all methods except Rfio (for which there would 
+  be no advantage); it is switched ON by default for Clear, Globus and Ssh,since 
+  it allows to speed up significantly repeated access to the same server.  
+  For SRP and Krb5 it is implemented but switched OFF by default, since it does 
+  not improve on authentication time (especially for Krb5).
+
+  Clear.ReUse:   yes
+  SRP.ReUse:     no
+  Krb5.ReUse:    0
+  Globus.ReUse:  yes
+  Ssh.ReUse:     1
+
+* Other directives
+
+  * Clear
+
+    * To secure password exchange set (this is the default)
+
+      Clear.Crypt   1
+
+      A session key pair is generated and used to encrypt the password hash to
+      be communicated to the server.
+
+  * globus
+
+    * to change the duration in hours of globus credentials (default is 12) use
+      Globus.ProxyDuration:     <hours>
+
+    * to change the number of bits in the key (default 1024)
+      Globus.ProxyKeyBits:      <bits>
+      where <bits> is 512 or 1024 or 2048 or 4096
+
+  * ssh
+
+    * to change the path with the 'ssh' executable
+      Ssh.ExecDir              <new_path>
+      (the executable will then be <new_path>/ssh)
+
+
+.authrootrc
+===========
+
+The .authrootrc file allow to specify host and user specific instructions; all
+the possibilities are explained in etc/example.authrootrc. The information read
+is used to instantiate THostAuth objects; these can be modified during the root
+session as explained in the next session.
+
+
+Modifying/Adding authentication info during the session
+=======================================================
+
+Remote authentication in root is controlled by the TAuthenticate class;
+TNetFile, TFTP and TSlave create a TAuthenticate object before proceeding to
+authentication.
+
+Authentication is (host,user) specific. The dedicated class THostAuth contains
+the information for a specific (host,user):
+
+       + remote host FQDN
+       + user name
+       + number of available methods n
+       + method internal codes (dimension n)
+       + login info for each method (dimension n)
+       + list of established authentication
+
+The available methods are listed in order of preference: the first one is the
+one preferred, the others are tried in turn upon failure of the previous one,
+and if accepted by the remote daemon (see Negotiation below).
+
+THostAuth objects are instantiated by TAuthenticate upon creation based on the
+information found in the files mentioned above. A set of methods are available
+in the TAuthenticate and THostAuth classes to display/modify/create THostAuth
+classes:
+
+ * void TAuthenticate::PrintHostAuth()
+
+   Prints the content of the instantiated THostAuth objects
+
+   Example:
+
+   root [1] TAuthenticate::PrintHostAuth()
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   Info in <THostAuth::Print>: + Host:pcepsft43.cern.ch - User:ganis - # of available methods:5
+   Info in <THostAuth::Print>: + Method: 3   Details:pt:no cd:~/.globus cf:usercert.pem kf:userkey.pem ad:certificates
+   Info in <THostAuth::Print>: + Method: 4   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 0   Details:pt:no us:ganis
+   Info in <THostAuth::Print>: + Method: 1   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 5   Details:pt:yes us:ganis
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   Info in <THostAuth::PrintEstablished>: +------------------------------------------------------------------+
+   Info in <THostAuth::PrintEstablished>: + Host:pcepsft43.cern.ch - Number of Established Authentications: 1
+   Info in <TAuthDetails::PrintEstblshd>: + Method:1 OffSet:278 Login:ganis Prompt:0 ReUse:1
+   Info in <TAuthDetails::PrintEstblshd>: +   Details:pt:0 ru:1 us:ganis
+   Info in <THostAuth::PrintEstablished>: +------------------------------------------------------------------+
+   root [2]
+
+   The method THostAuth::PrintEstablished is also called, displaying the
+   relevant info about successful authentications saved in TAuthDetails (see
+   below for details about TAuthDetails).
+
+ * THostAuth *TAuthenticate::GetHostAuth("<host_fqdn>","<user>")
+
+   Returns a pointer to the THostAuth object pertaining to (host,user) if it
+   exist, 0 otherwise.
+
+   Example:
+
+   root [2] THostAuth *ha = TAuthenticate::GetHostAuth("pcepsft43.cern.ch","ganis")
+   root [3] printf("ha: 0x%x\n",(int)ha);
+   ha: 0x88df970
+   root [4] THostAuth *ha = TAuthenticate::GetHostAuth("der.mit.ow","scruno")
+   root [5] printf("ha: 0x%x\n",(int)ha);
+   ha: 0x0
+   root [6]
+
+ * void TAuthenticate::ReadAuthRc("<host_fqdn>","<user>")
+
+   Loads information about (host,user) from .authrootrc or from the defaults in
+   .rootrc
+
+ * void TAuthenticate::RemoveHostAuth(THostAuth *ha)
+
+   Removes and destroys the THostAuth object pointed by ha from the static list
+   in TAuthenticate
+
+ * void THostAuth::Print()
+
+   Prints the information contained in this THostAuth object
+
+   Example:
+
+   root [7] THostAuth *ha = TAuthenticate::GetHostAuth("pcepsft43.cern.ch","ganis")
+   root [8] ha->Print()
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   Info in <THostAuth::Print>: + Host:pcepsft43.cern.ch - User:ganis - # of available methods:5
+   Info in <THostAuth::Print>: + Method: 3   Details:pt:no cd:~/.globus cf:usercert.pem kf:userkey.pem ad:certificates
+   Info in <THostAuth::Print>: + Method: 4   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 1   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 5   Details:pt:yes us:ganis
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   root [9]
+
+ * void THostAuth::AddMethod(<code>,<login_inf>)
+
+   Add a new method (internal code <code>, login information <login_info>) at
+   the end of the list of available methods
+
+   Example (with respect to above):
+
+   root [9] ha->AddMethod(0,"no us:ganis")
+   root [10] ha->Print()
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   Info in <THostAuth::Print>: + Host:pcepsft43.cern.ch - User:ganis - # of available methods:4
+   Info in <THostAuth::Print>: + Method: 3   Details:pt:no cd:~/.globus cf:usercert.pem kf:userkey.pem ad:certificates
+   Info in <THostAuth::Print>: + Method: 4   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 1   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 5   Details:pt:yes us:ganis
+   Info in <THostAuth::Print>: + Method: 0   Details:pt:no us:ganis
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   root [11]
+
+ * void THostAuth::RemoveMethod(<code>)
+
+   Removes method with internal code <code> from the list of available methods
+
+   Example (with respect to above):
+
+   root [9] ha->RemoveMethod(5)
+   root [10] ha->Print()
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   Info in <THostAuth::Print>: + Host:pcepsft43.cern.ch - User:ganis - # of available methods:4
+   Info in <THostAuth::Print>: + Method: 3   Details:pt:no cd:~/.globus cf:usercert.pem kf:userkey.pem ad:certificates
+   Info in <THostAuth::Print>: + Method: 4   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 1   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 0   Details:pt:no us:ganis
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   root [11]
+
+ * void THostAuth::SetDetails(<code>,<login_inf>)
+
+   Changes login info for method with internal code <code> to <login_info>; if
+   it does not exist, add a this as new method.
+
+   Example (with respect to above):
+
+   root [11] ha->SetDetails(4,"pt:no ru:1 us:gganis")
+   root [12] ha->Print()
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   Info in <THostAuth::Print>: + Host:pcepsft43.cern.ch - User:ganis - # of available methods:4
+   Info in <THostAuth::Print>: + Method: 3   Details:pt:no cd:~/.globus cf:usercert.pem kf:userkey.pem ad:certificates
+   Info in <THostAuth::Print>: + Method: 4   Details:pt:no ru:1 us:gganis
+   Info in <THostAuth::Print>: + Method: 1   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 0   Details:pt:no us:ganis
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   root [13]
+
+ * void THostAuth::SetFirst(<code>)
+
+   Set method with internal code <code> as the preferred one, if it exists.
+
+   Example (with respect to above):
+
+   root [13] ha->SetFirst(1)
+   root [14] ha->Print()
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   Info in <THostAuth::Print>: + Host:pcepsft43.cern.ch - User:ganis - # of available methods:4
+   Info in <THostAuth::Print>: + Method: 1   Details:pt:no ru:1 us:ganis
+   Info in <THostAuth::Print>: + Method: 3   Details:pt:no cd:~/.globus cf:usercert.pem kf:userkey.pem ad:certificates
+   Info in <THostAuth::Print>: + Method: 4   Details:pt:no ru:1 us:gganis
+   Info in <THostAuth::Print>: + Method: 0   Details:pt:no us:ganis
+   Info in <THostAuth::Print>: +------------------------------------------------------------------+
+   root [15]
+
+ * void THostAuth::SetFirst(<code>,<login_inf>)
+
+   Set method with internal code <code> as the preferred one, and changes the
+   login information to <login_inf>. If it does not exist, add a new method in
+   first position.
+
+ * void THostAuth::ReOrder(nmet,meths)
+
+   Reorder the list of the available methods in such a way that the first nmet
+   methods are the ones listed in meths[nmet].
+
+
+
+TAuthDetails
+============
+
+The class TAuthDetails contains the relevant details about a successful
+authentication to be used to speed up access to the same (host,user) entity
+during the same session. Each THostAuth contains a list of TAuthDetails objects
+pertaining to {host,user)
+
+
+
+
+
+
diff --git a/README/README.GLOBUS b/README/README.GLOBUS
new file mode 100644
index 0000000000000000000000000000000000000000..17aee0a18687eada625ada97560d9b027466ed2d
--- /dev/null
+++ b/README/README.GLOBUS
@@ -0,0 +1,232 @@
+
+Using Globus certificates to authenticate to a remote rootd/proofd server
+=========================================================================
+
+To use Globus certificates for remote authentication, the Globus Tool Kit
+should  be installed both in client and server machines and ROOT should be
+compiled with  the relevant flags set (see below).
+
+Globus Authentication has been tested for the moment only on Linux.
+
+1) Globus Tool Kit (GTK) Version
+
+   The interface has been developed using GTK version 2.2.3 and tested on
+   machines with version 2.0 and 2.0.21b; it should work with versions 2.x ;
+   however, vanilla versions 2.2.3 and 2.2.4 contain a bug which does not allow
+   to change online  at the same time the user certificate and key files, and
+   therefore to use all the features implemented in ROOT for this kind of
+   authentication. An experimental  patch is provided which however requires
+   access to the GTK source.
+
+
+2) Compiling ROOT with Globus support
+
+   To compile ROOT with Globus support run the 'configure' script with the flag
+   '--enable-globus'; the script expects the variable GLOBUS_LOCATION to be
+   defined and pointing to the location with the 'bin', 'lib' and 'include'
+   dirs for the  GTK . It is definitely better to have this variable defined
+   correctly (especially on the client side); however, for compilation purposes
+   it is possible to force  a specific directory for the GTK running configure
+   with
+
+       --with-globus-dir=<GTK_path>
+
+   The experimental patch mentioned above can be activated with the flag
+
+       --with-globus-patch-dir=<GTK_source>
+
+   where <GTK_source> points to the path containing the source of the GTK .
+
+   While running configure you should get the following printed
+
+ ...
+Checking for openssl/x509.h ... <Your_GLOBUS_LOCATION>/include/<flavour>
+Checking for openssl/pem.h ... <Your_GLOBUS_LOCATION>/include/<flavour>
+Checking for globus_gss_assist.h ... <Your_GLOBUS_LOCATION>/include/<flavour>
+Checking for libglobus_gss_assist_<flavour> ... <Your_GLOBUS_LOCATION>/lib
+Checking for libglobus_gssapi_gsi_<flavour> ... <Your_GLOBUS_LOCATION>/lib
+Checking for libssl_<flavour> ... <Your_GLOBUS_LOCATION>/lib
+Checking for libcrypto_<flavour> ... <Your_GLOBUS_LOCATION>/lib
+Checking for globus-user-env.sh ... <Your_GLOBUS_LOCATION>/etc
+Checking for grid-proxy-init ... <Your_GLOBUS_LOCATION>/bin
+Applying experimental patch to globus_gsi_system_config.c
+ ...
+   where <flavour> is either gcc32 or gcc32dbg. The last message appears only
+   if you  have activated the experimental patch mentioned above.
+
+3) Before running, after compilation/installation
+
+   3.1) On the CLIENT side
+
+        Make sure that valid certificates are in the correct places and that
+        valid credentials can be initialized; this can be tested by running
+
+               grid-proxy-init
+
+        and entering the pass phrase; you may have to source the relevant shell
+        file to have this command recognized:
+
+           source $GLOBUS_LOCATION/etc/globus-user-env.csh
+        or
+           source $GLOBUS_LOCATION/etc/globus-user-env.sh .
+
+        If you are sure about you capabilities to get valid credentials, you
+        don't need to initialize them outside the root session, for ROOT checks
+        the  credentials and prompts for the pass phrase if they are missing or
+        invalid.
+
+        There are three files/dirs relevant for proxy initialization:
+
+        a) user certificate file; default is $HOME/.globus/usercert.pem ; can
+           be  changed by setting the variable "X509_USER_CERT" to the full
+           path
+
+        b) user private key file; default is $HOME/.globus/userkey.pem ; can
+           be  changed by setting the variable "X509_USER_KEY" to the full path
+
+        c) directory with certificates of the known Certificate Authorities;
+           default is /etc/grid-security/certificates ; can be changed by
+           setting the variable "X509_CERT_DIR" to the full path.
+
+        All this variables can be changed by the user before running root or
+        during  a root session. Globus authentication can be requested by:
+
+        1) Setting
+
+                Rootd.Authentication   3
+                Proofd.Authentication   3
+
+           in the $HOME/.rootrc file; other parameters can be changed at this
+           level:
+
+          - the proxy duration, in hours
+
+                Globus.ProxyDuration :    <hours>
+
+          - the number of bits to be used for the key (should be a power of 2)
+
+                Globus.ProxyKeyBits:      1024
+
+          - a Globus login defining the relevant files mentioned above:
+
+                Globus.Login:             cd:~/.globus cf:usercert.pem  \
+                                          kf:userkey.pem  ad:certificates
+
+                with the meaning of the different keys being:
+
+                "cd"    defines the directory with the user certificate and
+                        private key; default: $HOME/.globus
+                "cf"    user certificate file (in the dir specified by "cd");
+                        default: usercert.pem
+                "kf"    user key file (in the dir specified by "cd");
+                        default: userkey.pem
+                "ad"    directory with certificates of the known Certificate
+                        Authorities; default: /etc/grid-security/certificates
+
+                Both "cd" and "ad" can be given as absolute paths (starting
+                with '/'), relative to  $HOME (starting with ~/) or relative to
+                $HOME/.globus (in the other cases).
+
+        2) Specifying an entry in .authrootrc (see README.AUTH for more details)
+
+           This allows to be host and user specific and to initialize proxies
+           for two or more  different users in the same session.
+
+        3) During a ROOT session by creating (or modifying) a THostAuth
+           instantiation  (see README.AUTH for more details)
+
+        Upon successful authentication the user is logged on remotely with the
+        user name  specified in the gridmap file on the remote server; if there
+        is no entry is found in  the gridmap corresponding to the client DN, an
+        attempt is made to guess it from the  CN part of the DN.
+
+
+   3.2) On the SERVER side
+
+        The servers rootd/proofd make use of the host certificate ( <CA bla
+        bla>/CN=host/<FQDN>) located by default in
+
+                    /etc/grid-security/hostcert.pem
+
+        and the related private key (default in
+        /etc/grid-security/hostkey.pem). The environment variable
+        X509_USER_CERT should be set to point to this file.
+
+        No proxies are needed for the host certificate.
+
+        Server Configuration file:
+        both daemon servers accept as argument
+
+                    -C <server_globus_conf_file>
+
+        By default this file is looked for in /etc/root/hostcert.conf or in
+        $ROOTSYS/etc/hostcert.conf and it contains record lines specifying
+
+        <certificates_dir>    <host_cert_file>  <host_cert_key> <grid_mapfile>
+
+        Record lines starting with '#' are considered as comments; an example:
+
+        < bof >
+        # This is an example of hostcert.conf ...
+        /etc/grid-security/certificates /etc/grid-security/hostcert.pem /etc/grid-security/hostkey.pem /etc/grid-security/grid-mapfile
+        < eof >
+
+        There may be as many line as there are valid certificate settings
+        (corresponding to  different Certificates Authorities and potentially
+        to different DN-to-UserName mappings ). When a request for globus
+        authentication arrives, rootd/proofd look among their  own certificates
+        if there is one issued by the same CA which has issued the  client
+        certificate; if the search is successful they communicate the related
+        subject name to the client and setenv the relevant variables using to
+        the chosen  configuration set.
+
+4) Trying out
+
+   Trying to access a remote file should give this on the client side (assuming
+   globus credentials have not been initialized before):
+
+root [1] TFile *f1 = TFile::Open("root://<remote_FQDN>/test.root","read")
+Your identity: /O=Grid/OU=GlobusTest/OU=simpleCA-arthux.cern.ch/OU=cern.ch/CN=qwerty
+Enter GRID pass phrase for this identity:
+Creating proxy ....................... Done
+Your proxy is valid until Wed May 28 02:46:12 2003
+root [2]
+
+   In the /var/log/messages on the server you should get something like ( with -d 3 in 'rootd')
+
+May 27 12:49:46 pcepsft43 rootd[24031]: RootdLoop: kind:2033 -- buf:'11820 -1 2 4 None' (len:17) -- Auth:0
+May 27 12:49:46 pcepsft43 rootd[24031]: RpdDefaultAuthAllow: default list of secure methods available:  4 1 2 3
+May 27 12:49:46 pcepsft43 rootd[24031]: RpdGlobusAuth: user: /O=Grid/OU=GlobusTest/OU=simpleCA-arthux.cern.ch/OU=cern.ch/CN=qwerty   authenticated
+May 27 12:49:46 pcepsft43 rootd[24031]: RpdGlobusAuth: logging as qwerty
+May 27 12:49:46 pcepsft43 rootd[24031]: RootdLogin: user qwerty authenticated (OffSet: -1)
+May 27 12:49:46 pcepsft43 rootd[24031]: RootdLoop: kind:2004 -- buf:'/test.root read' (len:10) -- Auth:1
+
+   The first authentication to a (remotehost,username) entity may be perceived
+   as slow;  this is because a lot of exchanges are need to establish the
+   security context; however,  the security context is kept until is valid, so
+   subsequent access to the same entity  will be much faster (if this is not
+   so, make sure that you do not have set the 'reuse'  flag to '0' or 'no'; see
+   README.AUTH).
+
+   In a PROOF cluster, if the master requires Globus credentials for
+   authentication  to slaves, these are automatically transmitted using a
+   shared memory.
+
+5) If it does not work ...
+
+   Some tips:
+
+   .1) make sure that local and remote times are synchronized within 5 minutes
+   .2) if GlobusAuthenticate is not found and you using /etc/ld.so.conf for
+       shared libraries you may need to run /sbin/ldconfig -v after compilation.
+   .3) Check location of certificate and private key files and certificate
+       directories; make sure they can be read by the root process
+   .4) Make sure that remote node accepts Globus authentication from your
+       local host
+   .5) Recompile with --with-globus-deb and check for more hints in the
+       flow of messages ...
+   .6) mailto: gerardo.ganis@cern.ch.
+
+--------------------------------------------------------------------------------------
+Last update: May 27, 2003
+
diff --git a/clib/inc/rsaaux.h b/clib/inc/rsaaux.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b5191cc08717b02f4c2e120e0331d4007d7d648
--- /dev/null
+++ b/clib/inc/rsaaux.h
@@ -0,0 +1,87 @@
+/* @(#)root/clib:$Name:  $:$Id: mmalloc.c,v 1.1.1.1 2000/05/16 17:00:43 rdm Exp $ */
+/* Author: */
+
+/*******************************************************************************
+*									       *
+*	Copyright (c) Martin Nicolay,  22. Nov. 1988			       *
+*									       *
+*	Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten   *
+*	bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter    *
+*	verwendet werden.						       *
+*									       *
+*	martin@trillian.megalon.de					       *
+*									       *
+*       ftp://ftp.funet.fi/pub/crypt/cryptography/asymmetric/rsa               *
+*									       *
+*       Simple RSA public key code.                                            *
+*       Adaptation in library for ROOT by G. Ganis, July 2003                  *
+*       (gerardo.ganis@cern.ch)                                                *
+*									       *
+*       Header used by internal rsa funtions                                   *
+*									       *
+*******************************************************************************/
+#ifndef	_RSAAUX_H
+#define	_RSAAUX_H
+
+#ifndef	_RSADEF_H
+#include "rsadef.h"
+#endif
+
+extern rsa_NUMBER a_one,a_two;
+
+/*
+ * Prototypes
+ */
+
+void	a_add		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+void	a_assign	P(( rsa_NUMBER*, rsa_NUMBER* ));
+int	a_cmp		P(( rsa_NUMBER*, rsa_NUMBER* ));
+void	a_div		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+void	a_div2		P(( rsa_NUMBER* ));
+void	a_ggt		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+void	a_imult		P(( rsa_NUMBER*, rsa_INT, rsa_NUMBER* ));
+void	a_mult		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+void	a_sub		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+void	m_init		P(( rsa_NUMBER*, rsa_NUMBER* ));
+void	m_add		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+void	m_mult		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+void	m_exp		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+int	n_bits		P(( rsa_NUMBER*, int));
+void	n_div		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+int	n_cmp		P(( rsa_INT*, rsa_INT*, int ));
+int	n_mult		P(( rsa_INT*, rsa_INT, rsa_INT*, int ));
+int	n_sub		P(( rsa_INT*, rsa_INT*, rsa_INT*, int, int ));
+int	n_bitlen	P(( rsa_NUMBER* ));
+
+
+
+/******************
+ * prim.h         *
+ ******************/
+
+int	p_prim		P(( rsa_NUMBER*, int ));
+void	inv		P(( rsa_NUMBER*, rsa_NUMBER*, rsa_NUMBER* ));
+
+
+/******************
+ * rnd.h          *
+ ******************/
+
+void	gen_number	P(( int, rsa_NUMBER* ));
+void	init_rnd	P(( void ));
+
+
+/******************
+ * aux.h          *
+ ******************/
+
+void   do_crypt(char *, char *, int, rsa_NUMBER *);
+
+/*
+int    get_clear(char *, FILE *);
+int    get_enc(char *, FILE *);
+int    put_clear(char *, FILE *);
+int    put_enc(char *, FILE *);
+*/
+
+#endif
diff --git a/clib/inc/rsadef.h b/clib/inc/rsadef.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6d87ca1a958cdaafd992bb4725f4bfbc77e814b
--- /dev/null
+++ b/clib/inc/rsadef.h
@@ -0,0 +1,122 @@
+/* @(#)root/clib:$Name:  $:$Id: mmalloc.c,v 1.1.1.1 2000/05/16 17:00:43 rdm Exp $ */
+/* Author: */
+
+/*******************************************************************************
+*									       *
+*	Copyright (c) Martin Nicolay,  22. Nov. 1988			       *
+*									       *
+*	Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten   *
+*	bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter    *
+*	verwendet werden.						       *
+*									       *
+*	martin@trillian.megalon.de					       *
+*									       *
+*       ftp://ftp.funet.fi/pub/crypt/cryptography/asymmetric/rsa               *
+*									       *
+*       Simple RSA public key code.                                            *
+*       Adaptation in library for ROOT by G. Ganis, July 2003                  *
+*       (gerardo.ganis@cern.ch)                                                *
+*									       *
+*       General rsa definitions header                                         *
+*									       *
+*******************************************************************************/
+
+#ifndef	_RSADEF_H
+#define	_RSADEF_H
+
+typedef	unsigned short rsa_INT;		/* muss MAXINT fassen		*/
+typedef	unsigned long rsa_LONG;		/* muss (MAXINT+1)^2 -1 fassen	*/
+
+#ifndef P
+#if defined (__STDC__) || defined (__cplusplus)
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+/*
+ *	(MAXINT+1)-adic Zahlen
+ */
+
+/*
+ *	MAXINT		Maximale Zahl pro Elemenmt (muss int sein)
+ *	MAXBIT		Maximales Bit von MAXINT
+ *	LOWBITS		Anzahl der consekutiven low Bits von MAXINT
+ *	HIGHBIT		Hoechsten Bit von MAXINT
+ *	TOINT		muss (INT)( (x) % MAXINT) ergeben
+ *	MAXLEN		Laenge der INT Array in jeder NUMBER
+ */
+
+#define rsa_MAXINT		0xFFFF
+
+#if rsa_MAXINT == 99
+#define	rsa_MAXBIT		7
+#define	rsa_LOWBITS 	2
+#endif
+#if rsa_MAXINT == 9
+#define	rsa_MAXBIT		4
+#define	rsa_LOWBITS 	1
+#endif
+#if rsa_MAXINT == 1
+#define rsa_MAXBIT		1
+#endif
+#if rsa_MAXINT == 0xFF
+#define rsa_MAXBIT		8
+#define	rsa_TOINT(x)	((rsa_INT)(x))		/* ACHTUNG !!!!! */
+#endif
+#if rsa_MAXINT == 0xFFFF
+#define rsa_MAXBIT		16
+#define	rsa_TOINT(x)	((rsa_INT)(x))		/* ACHTUNG !!!!! */
+#endif
+
+#ifndef	rsa_MAXBIT
+#include	"<< ERROR: rsa_MAXBIT must be defined >>"
+#endif
+#ifndef	rsa_LOWBITS
+#if rsa_MAXINT == (1 << rsa_MAXBIT) - 1
+#define	rsa_LOWBITS		rsa_MAXBIT
+#else
+#include	"<< ERROR: rsa_LOWBITS must be defined >>"
+#endif
+#endif
+
+#define	rsa_MAXLEN		(300*8/(rsa_MAXBIT + 1))
+#define	rsa_STRLEN		(rsa_MAXLEN*rsa_MAXBIT/4)
+#define	rsa_HIGHBIT		(1 << (rsa_MAXBIT-1) )
+
+#if rsa_LOWBITS == rsa_MAXBIT
+#define	rsa_DIVMAX1(x)	((x) >> rsa_MAXBIT)
+#define	rsa_MODMAX1(x)	((x) & rsa_MAXINT)
+#define	rsa_MULMAX1(x)	((x) << rsa_MAXBIT)
+#else
+#define	rsa_DIVMAX1(x)	((x) / (rsa_MAXINT+1))
+#define	rsa_MODMAX1(x)	((x) % (rsa_MAXINT+1))
+#define	rsa_MULMAX1(x)	((x) * (unsigned)(rsa_MAXINT+1))
+#endif
+
+#ifndef	rsa_TOINT
+#define	rsa_TOINT(x)	((rsa_INT)rsa_MODMAX1(x))
+#endif
+
+typedef struct {
+	int	n_len;			/* Hoechster benutzter Index	*/
+	rsa_INT	n_part[rsa_MAXLEN];
+} rsa_NUMBER;
+
+#define	rsa_NUM0P	((rsa_NUMBER *)0)		/* Abkuerzung			*/
+
+// Key structures
+typedef struct {
+        rsa_NUMBER n;   // modulus
+        rsa_NUMBER e;   // private or public exponent
+} rsa_KEY;
+typedef struct {
+        int   len;    //  length of 'data' in bytes
+        char *keys;   // 'HEX[n]#HEX[d]\0'
+} rsa_KEY_export;
+
+
+#endif
+
+
diff --git a/clib/inc/rsafun.h b/clib/inc/rsafun.h
new file mode 100644
index 0000000000000000000000000000000000000000..13ffb073196954947f4e72dbc1bc9237b7edacf4
--- /dev/null
+++ b/clib/inc/rsafun.h
@@ -0,0 +1,66 @@
+// @(#)root/clib:$Name:  $:$Id: TSocket.cxx,v 1.10 2002/05/18 08:22:00 brun Exp $
+// Author:
+
+/*******************************************************************************
+*									       *
+*	Copyright (c) Martin Nicolay,  22. Nov. 1988			       *
+*									       *
+*	Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten   *
+*	bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter    *
+*	verwendet werden.						       *
+*									       *
+*	martin@trillian.megalon.de					       *
+*									       *
+*       ftp://ftp.funet.fi/pub/crypt/cryptography/asymmetric/rsa               *
+*									       *
+*       Simple RSA public key code.                                            *
+*       Adaptation in library for ROOT by G. Ganis, July 2003                  *
+*       (gerardo.ganis@cern.ch)                                                *
+*									       *
+*       Hooks for useful rsa funtions                                          *
+**									       *
+*******************************************************************************/
+
+#include <stdio.h>
+
+#ifndef ROOT_rsafun
+#define ROOT_rsafun
+
+extern "C" {
+#ifndef _RSADEF_H
+#include "rsadef.h"
+#endif
+}
+
+
+typedef  rsa_NUMBER (*rsa_genprim_t)(int, int);
+typedef  int    (*rsa_genrsa_t)(rsa_NUMBER, rsa_NUMBER, rsa_NUMBER *, rsa_NUMBER *, rsa_NUMBER *);
+typedef  int    (*rsa_encode_t)(char *, int, rsa_NUMBER, rsa_NUMBER);
+typedef  int    (*rsa_decode_t)(char *, int, rsa_NUMBER, rsa_NUMBER);
+typedef  int	(*rsa_num_sput_t)(rsa_NUMBER*, char*, int );
+typedef  int	(*rsa_num_fput_t)(rsa_NUMBER*, FILE* );
+typedef  int	(*rsa_num_sget_t)(rsa_NUMBER*, char* );
+typedef  int	(*rsa_num_fget_t)(rsa_NUMBER*, FILE* );
+typedef  int    (*rsa_assign_t)(rsa_NUMBER *, rsa_NUMBER *);
+typedef  int    (*rsa_cmp_t)(rsa_NUMBER *, rsa_NUMBER *);
+
+
+class rsa_fun {
+
+public:
+   static rsa_genprim_t   fg_rsa_genprim;
+   static rsa_genrsa_t    fg_rsa_genrsa;
+   static rsa_encode_t    fg_rsa_encode;
+   static rsa_decode_t    fg_rsa_decode;
+   static rsa_num_sput_t  fg_rsa_num_sput;
+   static rsa_num_fput_t  fg_rsa_num_fput;
+   static rsa_num_sget_t  fg_rsa_num_sget;
+   static rsa_num_fget_t  fg_rsa_num_fget;
+   static rsa_assign_t    fg_rsa_assign;
+   static rsa_cmp_t       fg_rsa_cmp;
+
+   rsa_fun(rsa_genprim_t, rsa_genrsa_t, rsa_encode_t, rsa_decode_t,
+           rsa_num_sput_t, rsa_num_fput_t, rsa_num_sget_t, rsa_num_fget_t, rsa_assign_t, rsa_cmp_t);
+};
+
+#endif
diff --git a/clib/inc/rsalib.h b/clib/inc/rsalib.h
new file mode 100644
index 0000000000000000000000000000000000000000..12a19e6ba039aa8344d78532f81385aec51dcca0
--- /dev/null
+++ b/clib/inc/rsalib.h
@@ -0,0 +1,44 @@
+/* @(#)root/clib:$Name:  $:$Id: mmalloc.c,v 1.1.1.1 2000/05/16 17:00:43 rdm Exp $ */
+/* Author: */
+
+/*******************************************************************************
+*									       *
+*	Copyright (c) Martin Nicolay,  22. Nov. 1988			       *
+*									       *
+*	Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten   *
+*	bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter    *
+*	verwendet werden.						       *
+*									       *
+*	martin@trillian.megalon.de					       *
+*									       *
+*       ftp://ftp.funet.fi/pub/crypt/cryptography/asymmetric/rsa               *
+*									       *
+*       Simple RSA public key code.                                            *
+*       Adaptation in library for ROOT by G. Ganis, July 2003                  *
+*       (gerardo.ganis@cern.ch)                                                *
+*									       *
+*       prototypes for rsa funtions of public interest                         *
+*									       *
+*******************************************************************************/
+
+#ifndef	_RSALIB_H
+#define	_RSALIB_H
+
+rsa_NUMBER rsa_genprim(int, int);
+int    rsa_genrsa(rsa_NUMBER, rsa_NUMBER, rsa_NUMBER *, rsa_NUMBER *, rsa_NUMBER *);
+int    rsa_encode(char *, int, rsa_NUMBER, rsa_NUMBER);
+int    rsa_decode(char *, int, rsa_NUMBER, rsa_NUMBER);
+
+
+/******************
+ * nio.h          *
+ ******************/
+
+int	rsa_num_sput( rsa_NUMBER*, char*, int );
+int	rsa_num_fput( rsa_NUMBER*, FILE* );
+int	rsa_num_sget( rsa_NUMBER*, char* );
+int	rsa_num_fget( rsa_NUMBER*, FILE* );
+
+#endif
+
+
diff --git a/clib/src/rsaaux.c b/clib/src/rsaaux.c
new file mode 100644
index 0000000000000000000000000000000000000000..98de437a20b3fcd0497ed5c1f6d53cde0ed697f0
--- /dev/null
+++ b/clib/src/rsaaux.c
@@ -0,0 +1,1121 @@
+/* @(#)root/clib:$Name:  $:$Id: mmalloc.c,v 1.1.1.1 2000/05/16 17:00:43 rdm Exp $ */
+/* Author: */
+
+/*******************************************************************************
+*									       *
+*	Copyright (c) Martin Nicolay,  22. Nov. 1988			       *
+*									       *
+*	Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten   *
+*	bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter    *
+*	verwendet werden.						       *
+*									       *
+*	martin@trillian.megalon.de					       *
+*									       *
+*       ftp://ftp.funet.fi/pub/crypt/cryptography/asymmetric/rsa               *
+*									       *
+*       Simple RSA public key code.                                            *
+*       Adaptation in library for ROOT by G. Ganis, July 2003                  *
+*       (gerardo.ganis@cern.ch)                                                *
+*									       *
+*       Internal rsa funtions                                                  *
+*									       *
+*******************************************************************************/
+#include	<stdio.h>
+#include	<ctype.h>
+#include	<string.h>
+#include	<stdlib.h>
+
+#include	"rsaaux.h"
+#include	"rsalib.h"
+
+/*******************************************************************************
+*									       *
+* arith.c                                                                      *
+*                                                                              *
+********************************************************************************/
+
+/*
+ *	!!!!!!!!!!!!!!!!!!!!!!!!!!!! ACHTUNG !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *	Es findet keinerlei Ueberpruefung auf Bereichsueberschreitung
+ *	statt. Alle Werte muessen natuerliche Zahlen aus dem Bereich
+ *		0 ... (rsa_MAXINT+1)^rsa_MAXLEN-1 sein.
+ *
+ *
+ *	Bei keiner Funktion oder Hilsfunktion werden Annahmen getroffen,
+ *	ueber die Verschiedenheit von Eingabe- & Ausgabe-Werten.
+ *
+ *
+ *		Funktionen:
+ *
+ *	a_add( s1, s2, d )
+ *		rsa_NUMBER *s1,*s2,*d;
+ *			*d = *s1 + *s2;
+ *
+ *	a_assign( *d, *s )
+ *		rsa_NUMBER *d,*s;
+ *			*d = *s;
+ *
+ * int	a_cmp( c1, c2 )
+ *		rsa_NUMBER *c1,*c2;
+ *			 1 :	falls *c1 >  *c2
+ *			 0 :	falls *c1 == *c2
+ *			-1 :	falls *c1 <  *c2
+ *
+ *	a_div( d1, d2, q, r )
+ *		rsa_NUMBER *d1,*d2,*q,*r;
+ *			*q = *d1 / *d2 Rest *r;
+ *
+ *	a_div2( n )
+ *		rsa_NUMBER *n;
+ *			*n /= 2;
+ *
+ *	a_ggt( a, b, f )
+ *		rsa_NUMBER *a,*b,*f;
+ *			*f = ( *a, *b );
+ *
+ *	a_imult( n, m, d )
+ *		rsa_NUMBER *n;
+ *		rsa_INT m;
+ *		rsa_NUMBER *d;
+ *			*d = *n * m
+ *
+ *	a_mult( m1, m2, d )
+ *		rsa_NUMBER *m1,*m2,*d;
+ *			*d = *m1 * *m2;
+ *
+ *	a_sub( s1, s2, d )
+ *		rsa_NUMBER *s1,*s2,*d;
+ *			*d = *s1 - *s2;
+ *
+ *		Modulare Funktionen
+ *	m_init( n, o )
+ *		rsa_NUMBER *n,*o;
+ *			Initialsierung der Modularen Funktionen
+ *			o != 0 : *o = alter Wert
+ *
+ *	m_add( s1, s2, d )
+ *		rsa_NUMBER *s1, *s2, *d;
+ *			*d = *s1 + *s2;
+ *
+ *	m_mult( m1, m2, d )
+ *		rsa_NUMBER *m1,*m2,*d;
+ *
+ *	m_exp( x, n, z )
+ *		rsa_NUMBER *x,*n,*z;
+ *			*z = *x exp *n;
+ *
+ *
+ *		Hilfs-Funktionen:
+ *
+ * int	n_bits( n, b )
+ *		rsa_NUMBER *n;
+ *		int b;
+ *			return( unterste b Bits der Dualdarstellung von n)
+ *
+ *	n_div( d1, z2, q, r )
+ *		rsa_NUMBER *d1,z2[rsa_MAXBIT],*q,*r;
+ *			*q = *d1 / z2[0] Rest *r;
+ *			z2[i] = z2[0] * 2^i,  i=0..rsa_MAXBIT-1
+ *
+ * int	n_cmp( i1, i2, l )
+ *		rsa_INT i1[l], i2[l];
+ *			 1 :	falls i1 >  i2
+ *			 0 :	falls i1 == i2
+ *			-1 :	falls i1 <  i2
+ *
+ * int	n_mult( n, m, d, l)
+ *		rsa_INT n[l], m, d[];
+ *			d = m * n;
+ *			return( sizeof(d) ); d.h. 'l' oder 'l+1'
+ *
+ * int	n_sub( p1, p2, p3, l, lo )
+ *		rsa_INT p1[l], p2[lo], p3[];
+ *			p3 = p1 - p2;
+ *			return( sizeof(p3) ); d.h. '<= min(l,lo)'
+ *
+ * int	n_bitlen( n )
+ * 		rsa_NUMBER *n;
+ *			return( sizeof(n) in bits )
+ *
+ */
+
+
+/*
+ * Konstante 1, 2
+ */
+rsa_NUMBER a_one = {
+	1,
+	{ (rsa_INT)1, },
+};
+
+rsa_NUMBER a_two = {
+#if rsa_MAXINT == 1
+	2,
+	{ 0, (rsa_INT)1, },
+#else
+	1,
+	{ (rsa_INT)2, },
+#endif
+};
+
+
+/*
+ * Vergleiche zwei rsa_INT arrays der Laenge l
+ */
+int n_cmp( i1, i2, l )
+rsa_INT *i1,*i2;
+int l;
+{
+	i1 += (l-1);			/* Pointer ans Ende		*/
+	i2 += (l-1);
+
+	for (;l--;)
+		if ( *i1-- != *i2-- )
+			return( i1[1] > i2[1] ? 1 : -1 );
+
+	return(0);
+}
+
+/*
+ * Vergleiche zwei rsa_NUMBER
+ */
+int a_cmp( c1, c2 )
+rsa_NUMBER *c1,*c2;
+{
+	int l;
+					/* bei verschiedener Laenge klar*/
+	if ( (l=c1->n_len) != c2->n_len)
+		return( l - c2->n_len);
+
+					/* vergleiche als arrays	*/
+	return( n_cmp( c1->n_part, c2->n_part, l) );
+}
+
+/*
+ * Zuweisung einer rsa_NUMBER (d = s)
+ */
+void a_assign( d, s )
+rsa_NUMBER *d,*s;
+{
+	int l;
+
+	if (s == d)			/* nichts zu kopieren		*/
+		return;
+
+	if ((l=s->n_len))
+		memcpy( d->n_part, s->n_part, sizeof(rsa_INT)*l);
+
+	d->n_len = l;
+}
+
+/*
+ * Addiere zwei rsa_NUMBER (d = s1 + s2)
+ */
+void a_add( s1, s2, d )
+rsa_NUMBER *s1,*s2,*d;
+{
+	int l,lo,ld,same;
+	register rsa_LONG sum;
+	register rsa_INT *p1,*p2,*p3;
+	register rsa_INT b;
+
+				/* setze s1 auch die groessere Zahl	*/
+	l = s1->n_len;
+	if ( (l=s1->n_len) < s2->n_len) {
+		rsa_NUMBER *tmp = s1;
+
+		s1 = s2;
+		s2 = tmp;
+
+		l = s1->n_len;
+	}
+
+	ld = l;
+	lo = s2->n_len;
+	p1 = s1->n_part;
+	p2 = s2->n_part;
+	p3 = d->n_part;
+	same = (s1 == d);
+	sum = 0;
+
+	while (l --) {
+		if (lo) {		/* es ist noch was von s2 da	*/
+			lo--;
+			b = *p2++;
+		}
+		else
+			b = 0;		/* ansonten 0 nehmen		*/
+
+		sum += (rsa_LONG)*p1++ + (rsa_LONG)b;
+		*p3++ = rsa_TOINT(sum);
+
+		if (sum > (rsa_LONG)rsa_MAXINT) {	/* carry merken		*/
+			sum = 1;
+		}
+		else
+			sum = 0;
+
+		if (!lo && same && !sum)	/* nichts mehr zu tuen	*/
+			break;
+	}
+
+	if (sum) {		/* letztes carry beruecksichtigen	*/
+		ld++;
+		*p3 = sum;
+	}
+
+	d->n_len = ld;			/* Laenge setzen		*/
+}
+
+/*
+ * Subtrahiere zwei rsa_INT arrays. return( Laenge Ergebniss )
+ * l == Laenge p1
+ * lo== Laenge p3
+ */
+int n_sub( p1, p2, p3, l, lo )
+rsa_INT *p1,*p2,*p3;
+int l,lo;
+{
+	int ld,lc,same;
+	int over = 0;
+	register rsa_LONG dif;
+	rsa_LONG a,b;
+
+	same = (p1 == p3);			/* frueher Abbruch moeglich */
+
+	for (lc=1, ld=0; l--; lc++) {
+		a = (rsa_LONG)*p1++;
+		if (lo) {			/* ist noch was von p2 da ? */
+			lo--;
+			b = (rsa_LONG)*p2++;
+		}
+		else
+			b=0;			/* ansonten 0 nehmen	*/
+
+		if (over)			/* frueherer Overflow	*/
+			b++;
+		if ( b > a) {			/* jetzt Overflow ?	*/
+			over = 1;
+			dif = (rsa_MAXINT +1) + a;
+		}
+		else {
+			over = 0;
+			dif = a;
+		}
+		dif -= b;
+		*p3++ = (rsa_INT)dif;
+
+		if (dif)			/* Teil != 0 : Laenge neu */
+			ld = lc;
+		if (!lo && same && !over) {	/* nichts mehr zu tuen	*/
+			if (l > 0)		/* Laenge korrigieren	*/
+				ld = lc + l;
+			break;
+		}
+	}
+
+	return( ld );
+}
+
+/*
+ * Subtrahiere zwei rsa_NUMBER (d= s1 - s2)
+ */
+void a_sub( s1, s2, d )
+rsa_NUMBER *s1,*s2,*d;
+{
+	d->n_len = n_sub( s1->n_part, s2->n_part, d->n_part
+			 ,s1->n_len, s2->n_len );
+}
+
+/*
+ * Mulitipliziere rsa_INT array der Laenge l mit einer rsa_INT (d = n * m)
+ * return neue Laenge
+ */
+int n_mult( n, m, d, l)
+register rsa_INT *n;
+register rsa_INT m;
+rsa_INT *d;
+int l;
+{
+	int i;
+	register rsa_LONG mul;
+
+	for (i=l,mul=0; i; i--) {
+		mul += (rsa_LONG)m * (rsa_LONG)*n++;
+		*d++ = rsa_TOINT(mul);
+		mul  = rsa_DIVMAX1( mul );
+	}
+
+	if (mul) {		/* carry  ? */
+		l++;
+		*d = mul;
+	}
+
+	return( l );
+}
+
+/*
+ * Mulitipliziere eine rsa_NUMBER mit einer rsa_INT (d = n * m)
+ */
+void a_imult( n, m, d )
+rsa_NUMBER *n;
+rsa_INT m;
+rsa_NUMBER *d;
+{
+	if (m == 0)
+		d->n_len=0;
+	else if (m == 1)
+		a_assign( d, n );
+	else
+		d->n_len = n_mult( n->n_part, m, d->n_part, n->n_len );
+}
+
+/*
+ * Multipliziere zwei rsa_NUMBER (d = m1 * m2)
+ */
+void a_mult( m1, m2, d )
+rsa_NUMBER *m1,*m2,*d;
+{
+	static rsa_INT id[ rsa_MAXLEN ];		/* Zwischenspeicher	*/
+	register rsa_INT *vp;			/* Pointer darin	*/
+	register rsa_LONG sum;			/* Summe fuer jede Stelle */
+	register rsa_LONG tp1;			/* Zwischenspeicher fuer m1 */
+	register rsa_INT *p2;
+	rsa_INT *p1;
+	int l1,l2,ld,lc,l,i,j;
+
+	l1 = m1->n_len;
+	l2 = m2->n_len;
+	l = l1 + l2;
+	if (l >= rsa_MAXLEN)
+		abort();
+
+	for (i=l, vp=id; i--;)
+		*vp++ = 0;
+
+			/* ohne Uebertrag in Zwischenspeicher multiplizieren */
+	for ( p1 = m1->n_part, i=0; i < l1 ; i++, p1++) {
+
+		tp1 = (rsa_LONG)*p1;
+		vp = &id[i];
+		sum = 0;
+		for ( p2 = m2->n_part, j = l2; j--;) {
+			sum += (rsa_LONG)*vp + (tp1 * (rsa_LONG)*p2++);
+			*vp++ = rsa_TOINT( sum );
+			sum = rsa_DIVMAX1(sum);
+		}
+		*vp++ += (rsa_INT)sum;
+	}
+
+			/* jetzt alle Uebertraege beruecksichtigen	*/
+	ld = 0;
+	for (lc=0, vp=id, p1=d->n_part; lc++ < l;) {
+	   if ( (*p1++ = *vp++))
+			ld = lc;
+	}
+
+	d->n_len = ld;
+}
+
+
+/*
+ * Dividiere Zwei rsa_NUMBER mit Rest (q= d1 / z2[0] Rest r)
+ * z2[i] = z2[0] * 2^i,  i=0..rsa_MAXBIT-1
+ * r = 0 : kein Rest
+ * q = 0 : kein Quotient
+ */
+void n_div( d1, z2, q, r )
+rsa_NUMBER *d1,*z2,*q,*r;
+{
+	static	rsa_NUMBER dummy_rest;  /* Dummy Variable, falls r = 0 */
+	static	rsa_NUMBER dummy_quot;  /* Dummy Variable, falla q = 0 */
+	rsa_INT *i1,*i1e,*i3;
+	int l2,ld,l,lq;
+#if rsa_MAXINT != 1
+	rsa_INT z;
+	int pw,l2t;
+#endif
+
+	if (!z2->n_len)
+		abort();
+
+	if (!r)
+		r = &dummy_rest;
+	if (!q)
+		q = &dummy_quot;
+
+	a_assign( r, d1 );	/* Kopie von d1 in den Rest		*/
+
+	l2= z2->n_len;		/* Laenge von z2[0]			*/
+	l = r->n_len - l2;	/* Laenge des noch ''rechts'' liegenden
+					Stuecks von d1			*/
+	lq= l +1;		/* Laenge des Quotienten		*/
+	i3= q->n_part + l;
+	i1= r->n_part + l;
+	ld = l2;		/* aktuelle Laenge des ''Vergleichsstuecks''
+					von d1				*/
+	i1e= i1 + (ld-1);
+
+	for (; l >= 0; ld++, i1--, i1e--, l--, i3--) {
+		*i3 = 0;
+
+		if (ld == l2 && ! *i1e) {
+			ld--;
+			continue;
+		}
+
+		if ( ld > l2 || (ld == l2 && n_cmp( i1, z2->n_part, l2) >= 0) ) {
+#if rsa_MAXINT != 1
+				/* nach 2er-Potenzen zerlegen	*/
+			for (pw=rsa_MAXBIT-1, z=(rsa_INT)rsa_HIGHBIT; pw >= 0; pw--, z /= 2) {
+				if ( ld > (l2t= z2[pw].n_len)
+					|| (ld == l2t
+					    && n_cmp( i1, z2[pw].n_part, ld) >= 0)) {
+					ld = n_sub( i1, z2[pw].n_part, i1, ld, l2t );
+					(*i3) += z;
+				}
+			}
+#else
+				/* bei rsa_MAXINT == 1 alles viel einfacher	*/
+			ld = n_sub( i1, z2->n_part, i1, ld, l2 );
+			(*i3) ++;
+#endif
+		}
+	}
+
+			/* Korrektur, falls l von Anfang an Negativ war */
+	l ++;
+	lq -= l;
+	ld += l;
+
+	if (lq>0 && !q->n_part[lq -1])	/* evtl. Laenge korrigieren	*/
+		lq--;
+
+	q->n_len = lq;
+	r->n_len = ld -1;
+}
+
+/*
+ * Dividiere Zwei rsa_NUMBER mit Rest (q= d1 / z2[0] Rest r)
+ * z2[i] = z2[0] * 2^i,  i=0..rsa_MAXBIT-1
+ * r = 0 : kein Rest
+ * q = 0 : kein Quotient
+ */
+void a_div( d1, d2, q, r )
+rsa_NUMBER *d1,*d2,*q,*r;
+{
+#if rsa_MAXINT != 1
+	rsa_NUMBER z2[rsa_MAXBIT];
+	rsa_INT z;
+	int i;
+
+	a_assign( &z2[0], d2 );
+	for (i=1,z=2; i < rsa_MAXBIT; i++, z *= 2)
+		a_imult( d2, z, &z2[i] );
+
+	d2 = z2;
+#endif
+
+	n_div( d1, d2, q, r );
+}
+
+/*
+ * Dividiere eine rsa_NUMBER durch 2
+ */
+void a_div2( n )
+rsa_NUMBER *n;
+{
+#if rsa_MAXBIT == rsa_LOWBITS
+	register rsa_INT *p;
+	int i;
+
+#if rsa_MAXINT != 1
+	register rsa_INT h;
+	register int c;
+
+	c=0;
+	i= n->n_len;
+	p= &n->n_part[i-1];
+
+	for (; i--;) {
+		if (c) {
+			c = (h= *p) & 1;
+			h /= 2;
+			h |= rsa_HIGHBIT;
+		}
+		else {
+			c = (h= *p) & 1;
+			h /= 2;
+		}
+
+		*p-- = h;
+	}
+
+	if ( (i= n->n_len) && n->n_part[i-1] == 0 )
+		n->n_len = i-1;
+
+#else  /* rsa_MAXBIT != 1 */
+	p = n->n_part;
+	i = n->n_len;
+
+	if (i) {
+		n->n_len = i-1;
+		for (; --i ; p++)
+			p[0] = p[1];
+	}
+#endif /* rsa_MAXBIT != 1 */
+#else  /* rsa_MAXBIT == rsa_LOWBITS */
+	a_div( n, &a_two, n, rsa_NUM0P );
+#endif /* rsa_MAXBIT == rsa_LOWBITS */
+}
+
+
+/*
+ *	MODULO-FUNKTIONEN
+ */
+
+static rsa_NUMBER mod_z2[ rsa_MAXBIT ];
+
+/*
+ * Init
+ */
+void m_init( n, o )
+rsa_NUMBER *n,*o;
+{
+	rsa_INT z;
+	int i;
+
+	if (o)
+		a_assign( o, &mod_z2[0] );
+
+	if (! a_cmp( n, &mod_z2[0]) )
+		return;
+
+	for (i=0,z=1; i < rsa_MAXBIT; i++, z *= 2)
+		a_imult( n, z, &mod_z2[i] );
+}
+
+void m_add( s1, s2, d )
+rsa_NUMBER *s1, *s2, *d;
+{
+	a_add( s1, s2, d );
+	if (a_cmp( d, mod_z2) >= 0)
+		a_sub( d, mod_z2, d );
+}
+
+void m_mult( m1, m2, d )
+rsa_NUMBER *m1,*m2,*d;
+{
+	a_mult( m1, m2, d );
+	n_div( d, mod_z2, rsa_NUM0P, d );
+}
+
+/*
+ * Restklassen Exponent
+ */
+void m_exp( x, n, z )
+rsa_NUMBER *x,*n,*z;
+{
+	rsa_NUMBER xt,nt;
+
+	a_assign( &nt, n );
+	a_assign( &xt, x );
+	a_assign( z, &a_one );
+
+	while (nt.n_len) {
+		while ( ! (nt.n_part[0] & 1)) {
+			m_mult( &xt, &xt, &xt );
+			a_div2( &nt );
+		}
+		m_mult( &xt, z, z );
+		a_sub( &nt, &a_one, &nt );
+	}
+}
+
+/*
+ * GGT
+ */
+void a_ggt( a, b, f )
+rsa_NUMBER *a,*b,*f;
+{
+	rsa_NUMBER t[2];
+	int at,bt, tmp;
+
+	a_assign( &t[0], a ); at= 0;
+	a_assign( &t[1], b ); bt= 1;
+
+	if ( a_cmp( &t[at], &t[bt]) < 0) {
+		tmp= at; at= bt; bt= tmp;
+	}
+				/* euklidischer Algorithmus		*/
+	while ( t[bt].n_len) {
+		a_div( &t[at], &t[bt], rsa_NUM0P, &t[at] );
+		tmp= at; at= bt; bt= tmp;
+	}
+
+	a_assign( f, &t[at] );
+}
+
+/*
+ * die untersten b bits der Dualdarstellung von n
+ * die bits muessen in ein int passen
+ */
+int n_bits(n,b)
+rsa_NUMBER *n;
+int b;
+{
+	rsa_INT *p;
+	int l;
+	unsigned r;
+	int m = (1<<b) -1;
+
+	if ( n->n_len == 0)
+		return(0);
+
+	if (rsa_LOWBITS >= b)
+		return( n->n_part[0] & m );
+
+#if rsa_LOWBITS != 0
+	l = (b-1) / rsa_LOWBITS;
+#else
+	l = n->n_len -1;
+#endif
+	for (p= &n->n_part[l],r=0; l-- >= 0 && b > 0; b-= rsa_LOWBITS, p--) {
+		r  = rsa_MULMAX1( r );
+		r += (unsigned)*p;
+	}
+
+	return( r & m );
+}
+
+/*
+ * Anzahl der bits von n bei Dualdarstellung
+ */
+int n_bitlen( n )
+rsa_NUMBER *n;
+{
+	rsa_NUMBER b;
+	int i;
+
+	a_assign( &b, &a_one );
+
+	for (i=0; a_cmp( &b, n) <= 0; a_mult( &b, &a_two, &b ), i++)
+		;
+
+	return(i);
+}
+
+
+/*******************************************************************************
+*									       *
+* prim.c                                                                       *
+*                                                                              *
+********************************************************************************/
+
+/*
+ *		RSA
+ *
+ *	p,q prim
+ *	p != q
+ *	n = p*q
+ *	phi = (p -1)*(q -1)
+ *	e,d aus 0...n-1
+ *	e*d == 1 mod phi
+ *
+ *	m aus 0...n-1 sei eine Nachricht
+ *
+ *	Verschluesseln:
+ *		E(x) = x^e mod n		( n,e oeffendlich )
+ *
+ *	Entschluesseln:
+ *		D(x) = x^d mod n		( d geheim )
+ *
+ *
+ *	Sicherheit:
+ *
+ *		p,q sollten bei mind. 10^100 liegen.
+ *		(d,phi) == 1, das gilt fuer alle Primzahlen > max(p,q).
+ *		Allerdings sollte d moeglichst gross sein ( d < phi-1 )
+ *		um direktes Suchen zu verhindern.
+ */
+
+
+/*
+ *		FUNKTIONEN um RSA Schluessel zu generieren.
+ *
+ * int	p_prim( n, m )
+ *		rsa_NUMBER *n;
+ *		int m;
+ *			0 : n ist nicht prim
+ *			1 : n ist mit Wahrscheinlichkeit (1-1/2^m) prim
+ *		ACHTUNG !!!!
+ *		p_prim benutzt m_init
+ *
+ *	inv( d, phi, e )
+ *		rsa_NUMBER *d,*phi,*e;
+ *			*e = *d^-1 (mod phi)
+ *		ACHTUNG !!!!
+ *		p_prim benutzt m_init
+ */
+
+/*
+ * Prototypes
+ */
+static int	jak_f( rsa_NUMBER* );
+static int	jak_g( rsa_NUMBER*, rsa_NUMBER* );
+static int	jakobi( rsa_NUMBER*, rsa_NUMBER* );
+
+/*
+ * Hilfs-Funktion fuer jakobi
+ */
+static int jak_f( n )
+rsa_NUMBER *n;
+{
+	int f,ret;
+
+	f = n_bits( n, 3 );
+
+	ret = ((f == 1) || (f == 7)) ? 1 : -1;
+
+	return(ret);
+}
+
+/*
+ * Hilfs-Funktuion fuer jakobi
+ */
+static int jak_g( a, n )
+rsa_NUMBER *a,*n;
+{
+	int ret;
+
+	if ( n_bits( n, 2) == 1 ||
+			n_bits( a, 2) == 1 )
+		ret = 1;
+	else
+		ret = -1;
+
+	return(ret);
+}
+
+/*
+ * Jakobi-Symbol
+ */
+static int jakobi( a, n )
+rsa_NUMBER *a,*n;
+{
+	rsa_NUMBER t[2];
+	int at,nt, ret;
+
+	a_assign( &t[0], a ); at = 0;
+	a_assign( &t[1], n ); nt = 1;
+
+	/*
+	 * b > 1
+	 *
+	 * J( a, b) =
+	 * a == 1	:	1
+	 * a == 2	:	f(n)
+	 * a == 2*b	:	J(b,n)*J(2,n) ( == J(b,n)*f(n) )
+	 * a == 2*b -1	:	J(n % a,a)*g(a,n)
+	 *
+	 */
+
+	ret = 1;
+	while (1) {
+		if (! a_cmp(&t[at],&a_one)) {
+			break;
+		}
+		if (! a_cmp(&t[at],&a_two)) {
+			ret *= jak_f( &t[nt] );
+			break;
+		}
+		if ( ! t[at].n_len )		/* Fehler :-)	*/
+			abort();
+		if ( t[at].n_part[0] & 1) {	/* a == 2*b -1	*/
+			int tmp;
+
+			ret *= jak_g( &t[at], &t[nt] );
+			a_div( &t[nt], &t[at], rsa_NUM0P, &t[nt] );
+			tmp = at; at = nt; nt = tmp;
+		}
+		else {				/* a == 2*b	*/
+			ret *= jak_f( &t[nt] );
+			a_div2( &t[at] );
+		}
+
+	}
+
+	return(ret);
+}
+
+/*
+ * Probabilistischer Primzahltest
+ *
+ *  0 -> n nicht prim
+ *  1 -> n prim mit  (1-1/2^m) Wahrscheinlichkeit.
+ *
+ *	ACHTUNG !!!!!!
+ *	p_prim benutzt m_init !!
+ *
+ */
+int p_prim( n, m )
+rsa_NUMBER *n;
+int m;
+{
+	rsa_NUMBER gt,n1,n2,a;
+	rsa_INT *p;
+	int i,w,j;
+
+	if (a_cmp(n,&a_two) <= 0 || m <= 0)
+		abort();
+
+	a_sub( n, &a_one, &n1 );	/* n1 = -1    mod n		*/
+	a_assign( &n2, &n1 );
+	a_div2( &n2 );			/* n2 = ( n -1) / 2		*/
+
+	m_init( n, rsa_NUM0P );
+
+	w = 1;
+	for (; w && m; m--) {
+				/* ziehe zufaellig a aus 2..n-1		*/
+		do {
+			for (i=n->n_len-1, p=a.n_part; i; i--)
+				*p++ = (rsa_INT)rand();
+			if ((i=n->n_len) )
+				*p = (rsa_INT)( rand() % ((unsigned long)n->n_part[i-1] +1) );
+			while ( i && ! *p )
+				p--,i--;
+			a.n_len = i;
+		} while ( a_cmp( &a, n) >= 0 || a_cmp( &a, &a_two) < 0 );
+
+				/* jetzt ist a fertig			*/
+
+		/*
+		 * n ist nicht prim wenn gilt:
+		 *	(a,n) != 1
+		 * oder
+		 *	a^( (n-1)/2) != J(a,n)   mod n
+		 *
+		 */
+
+		a_ggt( &a, n, &gt );
+		if ( a_cmp( &gt, &a_one) == 0) {
+
+			j= jakobi( &a, n );
+			m_exp( &a, &n2, &a );
+
+			if  (   ( a_cmp( &a, &a_one) == 0 && j ==  1 )
+			     || ( a_cmp( &a, &n1   ) == 0 && j == -1) )
+				w = 1;
+			else
+				w = 0;
+		}
+		else
+			w = 0;
+	}
+
+	return( w );
+}
+
+/*
+ * Berechne mulitiplikatives Inverses zu d (mod phi)
+ *	d relativ prim zu phi ( d < phi )
+ *	d.h. (d,phi) == 1
+ *
+ *	ACHTUNG !!!!
+ *	inv benutzt m_init
+ */
+void inv( d, phi, e )
+rsa_NUMBER *d,*phi,*e;
+{
+	int k, i0, i1, i2;
+	rsa_NUMBER r[3],p[3],c;
+
+	/*
+	 * Berlekamp-Algorithmus
+	 *	( fuer diesen Spezialfall vereinfacht )
+	 */
+
+	if (a_cmp(phi,d) <= 0)
+		abort();
+
+	m_init( phi, rsa_NUM0P );
+
+	p[1].n_len = 0;
+	a_assign( &p[2], &a_one );
+	a_assign( &r[1], phi );
+	a_assign( &r[2], d );
+
+	k = -1;
+	do {
+		k++;
+		i0=k%3; i1=(k+2)%3; i2=(k+1)%3;
+		a_div( &r[i2], &r[i1], &c, &r[i0] );
+		m_mult( &c, &p[i1], &p[i0] );
+		m_add( &p[i0], &p[i2], &p[i0] );
+	} while (r[i0].n_len);
+
+	if ( a_cmp( &r[i1], &a_one) )	/* r[i1] == (d,phi) muss 1 sein	*/
+		abort();
+
+	if ( k & 1 )	/* falsches ''Vorzeichen''	*/
+		a_sub( phi, &p[i1], e );
+	else
+		a_assign( e, &p[i1] );
+}
+
+
+/*******************************************************************************
+*									       *
+* rnd.c                                                                       *
+*                                                                              *
+********************************************************************************/
+
+void gen_number( len, n )
+rsa_NUMBER *n;
+int len;
+{
+	char *hex = "0123456789ABCDEF" ;
+	char num[ rsa_MAXLEN*rsa_MAXBIT/4 +1 ];
+	char *p;
+	int i,l;
+
+	p=&num[ sizeof(num) -1];
+	*p-- = '\0';
+
+	for (l=len; l--; p--) {
+		i = rand() % 16;
+		*p = hex[ i ];
+	}
+	p++;
+
+	while (len-- && *p == '0')
+		p++;
+
+	rsa_num_sget( n, p );
+}
+
+void init_rnd()
+{
+	long time();
+	unsigned int seed;
+
+	seed = (unsigned int) time((long *)0);
+	(void)srand( seed );
+}
+
+
+/*******************************************************************************
+*									       *
+* aux.c                                                                       *
+*                                                                              *
+********************************************************************************/
+
+/* These are not needed, for the moment
+
+int get_clear( p, fp )
+char *p;
+FILE *fp;
+{
+	int n;
+
+	n = fread( p, 1, clear_siz, fp );
+
+	if (n <= 0)
+		return(0);
+
+	memset( p + n, 0, enc_siz - n );
+
+	return(1);
+}
+
+int get_enc( p, fp )
+char *p;
+FILE *fp;
+{
+	int n;
+
+	n = fread( p, 1, enc_siz, fp );
+
+	if (n != enc_siz)
+		return(0);
+
+	return(1);
+}
+
+int put_clear( p, fp )
+char *p;
+FILE *fp;
+{
+	int n;
+
+	n = fwrite( p, 1, clear_siz, fp );
+
+	if (n != clear_siz)
+		return(0);
+
+	return(1);
+}
+
+int put_enc( p, fp )
+char *p;
+FILE *fp;
+{
+	int n;
+
+	n = fwrite( p, 1, enc_siz, fp );
+
+	if (n != enc_siz)
+		return(0);
+
+	return(1);
+}
+
+*/
+
+void do_crypt( s, d, len, e )
+char *s;
+char *d;
+rsa_NUMBER *e;
+int len;
+{
+	static char hex[] = "0123456789ABCDEF";
+	rsa_NUMBER n;
+	char buf[ rsa_STRLEN + 1 ];
+	char *ph;
+	int i,c;
+
+	ph = buf + rsa_STRLEN;
+	ph[1] = '\0';
+
+	for (i=len; i; i--) {
+		c = *s++;
+		*ph-- = hex[ (c >> 4) & 0xF ];
+		*ph-- = hex[ c & 0xF ];
+	}
+	ph++;
+
+	rsa_num_sget( &n, ph );
+
+	m_exp( &n, e, &n );
+
+	rsa_num_sput( &n, buf, rsa_STRLEN +1 );
+
+	ph = buf + (i=strlen(buf)) -1;
+
+	for (; len; len--) {
+		if (i-- > 0) {
+			c = (strchr( hex, *ph) - hex) << 4;
+			ph--;
+		}
+		else
+			c=0;
+		if (i-- > 0) {
+			c |= strchr( hex, *ph) - hex;
+			ph--;
+		}
+
+		*d++ = c;
+	}
+}
+
diff --git a/clib/src/rsafun.cxx b/clib/src/rsafun.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1003b1d6605a57b3fcdb3857b8d3a7769eb6c840
--- /dev/null
+++ b/clib/src/rsafun.cxx
@@ -0,0 +1,71 @@
+// @(#)root/clib:$Name:  $:$Id: TSocket.cxx,v 1.10 2002/05/18 08:22:00 brun Exp $
+// Author:
+
+/*******************************************************************************
+*									       *
+*	Copyright (c) Martin Nicolay,  22. Nov. 1988			       *
+*									       *
+*	Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten   *
+*	bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter    *
+*	verwendet werden.						       *
+*									       *
+*	martin@trillian.megalon.de					       *
+*									       *
+*       ftp://ftp.funet.fi/pub/crypt/cryptography/asymmetric/rsa               *
+*									       *
+*       Simple RSA public key code.                                            *
+*       Adaptation in library for ROOT by G. Ganis, July 2003                  *
+*       (gerardo.ganis@cern.ch)                                                *
+*									       *
+*       Hooks for useful rsa funtions                                          *
+*									       *
+*******************************************************************************/
+
+#include "rsafun.h"
+
+
+extern "C" {
+   rsa_NUMBER rsa_genprim(int, int);
+   int    rsa_genrsa(rsa_NUMBER, rsa_NUMBER, rsa_NUMBER *, rsa_NUMBER *, rsa_NUMBER *);
+   int    rsa_encode(char *, int, rsa_NUMBER, rsa_NUMBER);
+   int    rsa_decode(char *, int, rsa_NUMBER, rsa_NUMBER);
+   int	  rsa_num_sput( rsa_NUMBER*, char*, int );
+   int	  rsa_num_fput( rsa_NUMBER*, FILE* );
+   int	  rsa_num_sget( rsa_NUMBER*, char* );
+   int	  rsa_num_fget( rsa_NUMBER*, FILE* );
+   int	  rsa_assign( rsa_NUMBER*, rsa_NUMBER* );
+   int	  rsa_cmp( rsa_NUMBER*, rsa_NUMBER* );
+}
+
+rsa_genprim_t  rsa_fun::fg_rsa_genprim;
+rsa_genrsa_t   rsa_fun::fg_rsa_genrsa;
+rsa_encode_t   rsa_fun::fg_rsa_encode;
+rsa_decode_t   rsa_fun::fg_rsa_decode;
+rsa_num_sput_t rsa_fun::fg_rsa_num_sput;
+rsa_num_fput_t rsa_fun::fg_rsa_num_fput;
+rsa_num_sget_t rsa_fun::fg_rsa_num_sget;
+rsa_num_fget_t rsa_fun::fg_rsa_num_fget;
+rsa_assign_t   rsa_fun::fg_rsa_assign;
+rsa_cmp_t      rsa_fun::fg_rsa_cmp;
+
+// Static instantiation to load hooks during dynamic load
+static rsa_fun  rsa_init(&rsa_genprim,&rsa_genrsa,&rsa_encode,&rsa_decode,
+                         &rsa_num_sput,&rsa_num_fput,&rsa_num_sget,&rsa_num_fget,&rsa_assign,&rsa_cmp);
+
+rsa_fun::rsa_fun(rsa_genprim_t genprim, rsa_genrsa_t genrsa, rsa_encode_t encode, rsa_decode_t decode,
+                 rsa_num_sput_t num_sput, rsa_num_fput_t num_fput, rsa_num_sget_t num_sget, rsa_num_fget_t num_fget,
+                 rsa_assign_t assign, rsa_cmp_t cmp)
+{
+  // ctor
+
+  fg_rsa_genprim = genprim;
+  fg_rsa_genrsa  = genrsa;
+  fg_rsa_encode  = encode;
+  fg_rsa_decode  = decode;
+  fg_rsa_num_sput = num_sput;
+  fg_rsa_num_fput = num_fput;
+  fg_rsa_num_sget = num_sget;
+  fg_rsa_num_fget = num_fget;
+  fg_rsa_assign   = assign;
+  fg_rsa_cmp      = cmp;
+}
diff --git a/clib/src/rsalib.c b/clib/src/rsalib.c
new file mode 100644
index 0000000000000000000000000000000000000000..6b1e0baff9762ab3715b8a3b853aac26538a0d9a
--- /dev/null
+++ b/clib/src/rsalib.c
@@ -0,0 +1,482 @@
+/* @(#)root/clib:$Name:  $:$Id: mmalloc.c,v 1.1.1.1 2000/05/16 17:00:43 rdm Exp $ */
+/* Author: */
+
+/*******************************************************************************
+*									       *
+*	Copyright (c) Martin Nicolay,  22. Nov. 1988			       *
+*									       *
+*	Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten   *
+*	bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter    *
+*	verwendet werden.						       *
+*									       *
+*	martin@trillian.megalon.de					       *
+*									       *
+*       ftp://ftp.funet.fi/pub/crypt/cryptography/asymmetric/rsa               *
+*									       *
+*       Simple RSA public key code.                                            *
+*       Adaptation in library for ROOT by G. Ganis, July 2003                  *
+*       (gerardo.ganis@cern.ch)                                                *
+*									       *
+*       rsa funtions of public interest                                        *
+*									       *
+*******************************************************************************/
+
+#include	<stdio.h>
+#include	<string.h>
+#include	<ctype.h>
+#include	<stdlib.h>
+#include        <errno.h>
+
+#include	"rsaaux.h"
+#include	"rsalib.h"
+
+static int	clear_siz;		/* clear-text blocksize		*/
+static int	enc_siz;		/* encoded blocksize		*/
+					/* clear_siz < enc_siz		*/
+
+int gLog = 0;
+
+rsa_NUMBER rsa_genprim(int len, int prob)
+{
+        rsa_NUMBER a_three,a_four;
+	rsa_NUMBER prim;
+	int i;
+
+	a_add( &a_one, &a_two, &a_three );
+	a_add( &a_two, &a_two, &a_four );
+
+	init_rnd();
+
+	do {
+		gen_number( len, &prim );
+	} while ( !prim.n_len );
+
+	a_mult( &prim, &a_two, &prim );
+	a_mult( &prim, &a_three, &prim );
+	a_add( &prim, &a_one, &prim );
+
+	for (i=1 ;; i++) {
+
+		if (p_prim( &prim, prob ))
+			break;
+		if (i % 2)
+			a_add( &prim, &a_four, &prim );
+		else
+			a_add( &prim, &a_two, &prim );
+	}
+
+	return prim;
+}
+
+int rsa_genrsa(rsa_NUMBER p1, rsa_NUMBER p2, rsa_NUMBER *n, rsa_NUMBER *e, rsa_NUMBER *d)
+{
+	rsa_NUMBER phi, *max_p;
+	int len;
+
+	if ( !a_cmp( &p1, &p2) ) return 1;
+
+	if (a_cmp( &p1, &p2) > 0)
+		max_p = &p1;
+	else
+		max_p = &p2;
+
+
+	a_mult( &p1, &p2, n );
+	a_sub( &p1, &a_one, &phi );
+	a_sub( &p2, &a_one, e );
+	a_mult( &phi, e, &phi );
+
+	len = n_bitlen( &phi );
+	len = ( len + 3) / 4;
+
+	a_assign( &p1, &phi );
+	a_sub( &p1, &a_one, &p1 );
+
+	init_rnd();
+
+	do {
+		do {
+			gen_number( len, d );
+		} while (a_cmp( d, max_p) <= 0 || a_cmp( d, &p1) >= 0);
+
+		a_ggt( d, &phi, e );
+	} while ( a_cmp( e, &a_one) );
+
+	inv( d, &phi, e );
+
+        return 0;
+}
+
+
+int rsa_encode(char *bufin, int lin, rsa_NUMBER n, rsa_NUMBER e)
+{
+  /* Encodes plain string in 'bufin' (output in 'bufin')
+     Returns length of encoded string
+     (key validity is not checked) */
+
+    char  buf[ rsa_STRLEN*2 ];
+    char  bufout[ rsa_STRLEN*2 ];
+    int   i, j, lout;
+    char *pout;
+
+    enc_siz = ( n_bitlen( &n) + 7) / 8;
+    clear_siz = enc_siz -1;
+    m_init( &n, rsa_NUM0P );
+
+    pout = bufout;
+    lout = 0;
+    for ( i = 0; i < lin; i += clear_siz) {
+
+      memcpy(buf,bufin+i,clear_siz);
+
+      j = ((lin-i) < clear_siz) ? lin-i : clear_siz;
+      memset(buf+j,0,(enc_siz-j));
+
+      do_crypt( buf, buf, enc_siz, &e );
+
+      memcpy(pout,buf,enc_siz);
+
+      pout += enc_siz;
+      lout += enc_siz;
+    }
+
+    memcpy(bufin,bufout,lout);
+
+    return lout;
+
+}
+
+int rsa_decode(char *bufin, int lin, rsa_NUMBER n, rsa_NUMBER e)
+{
+  /* Decodes string in 'bufin' (output in 'bufin')
+     Returns length of plaintext string
+     (key validity is not checked) */
+
+    char  buf[ rsa_STRLEN*2 ];
+    char  bufout[ rsa_STRLEN*2 ];
+    int   i, lout;
+    char *pout;
+
+    enc_siz = ( n_bitlen( &n) + 7) / 8;
+    clear_siz = enc_siz -1;
+    m_init( &n, rsa_NUM0P );
+
+    pout = bufout;
+    lout = 0;
+    for ( i = 0; i < lin; i += enc_siz) {
+
+      memcpy(buf,bufin+i,enc_siz);
+
+      do_crypt( buf, buf, enc_siz, &e );
+
+      memcpy(pout,buf,clear_siz);
+
+      pout += clear_siz;
+      lout += clear_siz;
+    }
+
+    memcpy(bufin,bufout,lout);
+
+    return lout;
+
+}
+
+
+/*******************************************************************************
+*									       *
+* nio.c                                                                        *
+*                                                                              *
+********************************************************************************/
+
+
+/*
+ *	rsa_NUMBER io
+ */
+
+/*
+ *		Funktionen
+ *
+ * int	num_sput( n, s, l)
+ *		rsa_NUMBER *n;
+ *		char s[l];
+ *			schreibt *n als Hex-Zahl in s
+ *
+ * int	num_fput( n, f )
+ *		rsa_NUMBER *n;
+ *		FILE *f;
+ *			schreibt *n als Hex-Zahl in File f
+ *
+ * int	num_sget( n, s )
+ *		rsa_NUMBER *n;
+ *		char *s;
+ *			liest Hex-Zahl s in *n ein
+ *
+ * int	num_fget( n, f )
+ *		rsa_NUMBER *n;
+ *		FILE *f;
+ *			liest eine Hex-Zahl von f in *n ein
+ *
+ */
+
+
+static char *HEX="0123456789ABCDEF";
+static char *hex="0123456789abcdef";
+
+static rsa_NUMBER bits[9];
+static rsa_NUMBER int16[16];
+
+static int init = 0;
+
+void num_init()
+{
+	int i;
+
+        if (init) return;
+
+	a_assign( &bits[0], &a_one );
+	for ( i=1; i<9; i++)
+		a_add( &bits[i-1], &bits[i-1], &bits[i] );
+
+	a_assign( &int16[0], &a_one );
+	for ( i=1; i<16; i++)
+		a_add( &int16[i-1], &a_one, &int16[i] );
+
+	init = 1;
+}
+
+
+int rsa_num_sput( n, s, l)
+rsa_NUMBER *n;
+char *s;
+int l;
+{
+#if rsa_MAXINT == ( (1 << rsa_MAXBIT) - 1 )
+	rsa_INT *p;
+	int bi,ab,i;
+	long b;
+	int first = 1;
+
+	bi = rsa_MAXBIT * n->n_len;
+	ab = 4 - (bi + 3) % 4 -1;
+	p  = &n->n_part[n->n_len -1];
+
+	if ( (bi+3) / 4 >= l )
+		return(EOF);
+
+	b  = 0;
+	while (bi) {
+		b <<= (rsa_MAXBIT);
+		b |= (unsigned long)*p--;
+		bi -= rsa_MAXBIT;
+		ab += rsa_MAXBIT;
+		while (ab >= 4) {
+			i = (b >> (ab - 4));
+			b &= ( 1L << (ab - 4)) -1L;
+			ab -= 4;
+
+			if (first && !i)
+				continue;
+			first = 0;
+			*s++ = HEX[ i ];
+		}
+	}
+	if (b)
+		abort();
+	*s = '\0';
+
+	return (0);
+#else
+	rsa_NUMBER r,q;
+	int i,b,p,len,low,high;
+	char *np;
+
+	if (! init)
+		num_init();
+
+	a_assign( &q, n);
+	len = l;
+	np = s + l;
+
+	for (; q.n_len && len > 1; len --) {
+		a_div( &q, &bits[4], &q, &r );
+		for (p=8, b=0, i=3; i >= 0; i--, p /= 2) {
+			if ( a_cmp( &r, &bits[i]) >= 0) {
+				a_sub( &r, &bits[i], &r );
+				b += p;
+			}
+		}
+		*--np = HEX[ b ];
+	}
+	if (q.n_len)
+		return(EOF);
+
+	l -= len;
+	len = l;
+	for (; l--; )
+		*s++ = *np++;
+
+	*s = '\0';
+
+	return (0);
+#endif
+}
+
+
+int rsa_num_fput( n, f )
+rsa_NUMBER *n;
+FILE *f;
+{
+	int j;
+	char *np;
+	char n_print[ rsa_STRLEN + 1 ];
+
+	if ( rsa_num_sput( n, n_print, sizeof( n_print) ) == EOF )
+		return(EOF);
+
+	for (j=0, np=n_print; *np ; np++, j++) {
+		if (j==64) {
+			fputs("\n",f);
+			j = 0;
+		}
+		putc((int)*np,f);
+	}
+
+	if (j)
+		putc('\n',f);
+
+	return(0);
+}
+
+
+int rsa_num_sget( n, s )
+rsa_NUMBER *n;
+char *s;
+{
+#if rsa_MAXINT == ( (1 << rsa_MAXBIT) - 1 )
+	rsa_INT *p;
+	char *hp;
+	int bi,ab,i;
+	long b;
+	int first = 1;
+
+	bi = 4 * strlen(s);
+	ab = rsa_MAXBIT - (bi + rsa_MAXBIT -1) % rsa_MAXBIT -1;
+	i  =  (bi + rsa_MAXBIT-1) / rsa_MAXBIT;
+	p  = &n->n_part[ i -1 ];
+	n->n_len = i;
+
+	if ( i > rsa_MAXLEN )
+		return(EOF);
+
+	b  = 0;
+	while (bi > 0) {
+		if ( (hp = strchr( HEX, *s )) )
+			i = hp - HEX;
+		else if ((hp = strchr( hex, *s )) )
+			i = hp - hex;
+		else
+			return(EOF);
+		s++;
+
+		b <<= 4;
+		b |= (unsigned long)i;
+		bi -= 4;
+		ab += 4;
+		while (ab >= rsa_MAXBIT) {
+			i = (b >> (ab - rsa_MAXBIT));
+			b &= ( 1L << (ab - rsa_MAXBIT)) -1L;
+			ab -= rsa_MAXBIT;
+			if (first && !i) {
+				p--;
+				n->n_len--;
+			}
+			else {
+				first = 0;
+				*p-- = i;
+			}
+		}
+	}
+	if (b)
+		abort();
+	*s = '\0';
+
+	return (0);
+#else
+	char *p;
+	int i,c;
+
+	if (! init)
+		num_init();
+
+	n->n_len = 0;
+	while ( (c = *s++ & 0xFF)) {
+		if ( p= strchr( HEX, c) )
+			i = p - HEX;
+		else if ( p= strchr( hex, c) )
+			i = p - hex;
+		else
+			return(EOF);
+
+		a_mult( n, &bits[4], n );
+		if (i)
+			a_add( n, &int16[i-1], n );
+	}
+
+	return(0);
+#endif
+}
+
+int rsa_num_fget( n, f )
+rsa_NUMBER *n;
+FILE *f;
+{
+	int j,c;
+	char *np;
+	char n_print[ rsa_STRLEN + 1 ];
+
+	np = n_print;
+	j = sizeof(n_print);
+	while ( (c=getc(f)) != EOF && ( isxdigit(c) || isspace(c)) ) {
+		if (isspace(c))
+			continue;
+		if (! --j)
+			return(EOF);
+		*np++ = (char)c;
+	}
+	*np = '\0';
+
+	if (c != EOF)
+		ungetc(c,f);
+
+	if ( rsa_num_sget( n, n_print) == EOF )
+		return( EOF );
+
+	return(0);
+}
+
+int rsa_cmp( c1, c2 )
+rsa_NUMBER *c1,*c2;
+{
+	int l;
+					/* bei verschiedener Laenge klar*/
+	if ( (l=c1->n_len) != c2->n_len)
+		return( l - c2->n_len);
+
+					/* vergleiche als arrays	*/
+	return( n_cmp( c1->n_part, c2->n_part, l) );
+}
+
+void rsa_assign( d, s )
+rsa_NUMBER *d,*s;
+{
+	int l;
+
+	if (s == d)			/* nichts zu kopieren		*/
+		return;
+
+	if ((l=s->n_len))
+		memcpy( d->n_part, s->n_part, sizeof(rsa_INT)*l);
+
+	d->n_len = l;
+}
+
diff --git a/etc/example.rootauthrc b/etc/example.rootauthrc
new file mode 100644
index 0000000000000000000000000000000000000000..fe7dccb84038f810e1bf2483e0251f006ad573df
--- /dev/null
+++ b/etc/example.rootauthrc
@@ -0,0 +1,194 @@
+#
+#  Example of .rootauthrc
+#
+#  (NB: ROOT assumes this file to be $HOME/.rootauthrc, this can be changed
+#       by setting the environment variable ROOTAUTHRC to the appropriate 
+#       absolute file pathname)
+#
+#  This file contains information about authentication methods available for
+#  authentication vis-a-vis of a given host. It allows to define host specific
+#  methods and defaults for the info (username, certificates, ...) to be used.
+#  The information specified here superseeds the one found in .rootrc.
+#  
+#  Format:
+#    - lines starting with '#' are comment lines.
+#
+#    - lines of the form 'include <file>' allow to include other files
+#      of this kind which are expanded exactly at the point where the 
+#      'include' appears.
+#
+#    - lines of the form:
+#
+#         proofserv <host1>[:<user1>][:<method1>] \
+#                   <host2>[:<user2>][:<method2>] \
+#                   <host3>[:<user3>][:<method3>] ...
+#
+#      are active only for PROOF sessions and specify the list of hosts 
+#      for which the authentication info should be transmitted to the master
+#      of the PROOF cluster; these directives are useful, for example, in
+#      the case of data servers external to the PROOF cluster that you may
+#      want to access via a given 'user' and a given authentication 'method'; 
+#      'user' and 'method' are not mandatory; for each <host> (an user, method)
+#      specified with 'proofserv' all the information that can be collected 
+#      from the rest of the .rootauthrc file is sent to the master. 
+#
+#    - remaining valid lines are of the form:
+#
+#         <host> [user <username>] <key> <info>
+#
+#      where <host> is the host(s) identifier (see below), <key> is an 
+#      option key and <info> is the relevant info whose format depends 
+#      on <key>; 'user' indicates the username to whom the information
+#      applies; if absent, the info applies to all users.
+#
+#      <host>:
+#         - hosts can specified either with their FQDN (e.g. pcepsft43.cern.ch)
+#           or their IP address (e.g. 137.138.99.73).
+#         - if <host>=default the following i<key> <info> applies to all 
+#           hosts, unless host-specific entries are found.
+#         - the '*' character can be used in the first field of the name to 
+#           indicate a set of machines, e.g. pcepsft*.cern.ch applies to all 
+#           'pcepsft' machines in the domain 'cern.ch'
+#           (to indicate all 'lxplus' machines you should use 'lxplus*.cern.ch'
+#           because internally the generic lxplus machine has a real name of
+#           the form lxplusnnn.cern.ch).
+#         - a whole domain can be indicated by its name, with at least two non 
+#           null fields, eg 'cern.ch' or '.cern.ch', '.ch' is not accepted.
+#         - subsets of the IP address can also be used to indicate a set of
+#           machines; however, it is mandatory to end the subset with a '.', 
+#           e.g. '137.138.' is an alternative way to indicate the 'cern.ch'
+#           domain, but '137.138' is invalid because ambiguous.
+#
+#      <key> <info>:
+#         - valid keys are 'list' and 'method';
+#         - if <key>=list, <info> contains the list of codes or short names for 
+#           methods that can/should be tried for authentication wrt to <host>, 
+#           in order of preference.
+#           Available methods are:
+#
+#              Method                        short name      code
+#
+#              UsrPwd                         usrpwd          0
+#              SRP                            srp             1
+#              Kerberos                       krb5            2
+#              Globus                         globus          3
+#              SSH                            ssh             4
+#              UidGid                         uidgid          5   (insecure)
+#
+#           Example of a valid 'list' line:
+#
+#              default          list  4 
+#              lxplus*.cern.ch  list  ssh 3 krb5
+#
+#           The first line defines as default method SSH, this is equivalent
+#           of setting:
+#
+#              Rootd.Authentication    4
+#              Proofd.Authentication   4
+#
+#           in the .rootc file.
+#
+#           The second line adds Globus and Kerberos as available methods
+#           for authentication to the lxplus machines (in addition to SSH):
+#           SSH the preferred first, Kerberos the last option. 
+#
+#           Having a line 'list' for a host is non mandatory: methods can
+#           also be defined directly via 'method' lines (see below); in
+#           such a case the first 'method' line will define the preferred
+#           method and so on.
+#
+#         - if <key>=method, <info> contains 
+#              + a method code  --> mandatory, must be in the valid range
+#              + a prompt flag  --> optional, identified by the key 'pt:',
+#                                   e.g. pt:yes
+#                                   values: 'yes' or 1, 'no' or '0'
+#              + a reuse flag   --> optional, identified by the key 'ru:',
+#                                   e.g. ru:no
+#                                   values: 'yes' or 1, 'no' or '0'
+#              + some relevant information for authentication (optional,
+#                see below)
+#
+#           The 'prompt' flag defines whether the user should be prompted
+#           for the relevant authentication details each time an 
+#           authentication with the corresponding method is attempted.
+#           Default is 'yes', superseeded by the related entry in '.rootrc' .
+#           The 'reuse' flag determines if a successful authentication will
+#           be later re-used without prompting (e.g. when the user tries
+#           to access the same host with same method during the same
+#           session: this allows to speed up operation in case of multiple
+#           access). Default is 'yes' for methods 0 (UsrPwd), 3 (Globus)
+#           and 4 (SSH), superseeded by the related entries in '.rootrc';
+#           feature not yet implemented for methods 1 (SRP) and 2 (Kerberos). 
+#           No additional info is needed by method 5 (UidGid): this method
+#           sends to the remote host the (uid,gid) of the current process;
+#           'reuse' will be af no advantage and 'prompt' is not allowed for
+#           security reasons. The format for the default info depends on
+#           the method:
+#
+#              Method                       Format info
+#
+#              UsrPwd                       us:<username> cp:<crypt_option>
+#              SRP                          us:<username> 
+#              Kerberos                     us:<principal> 
+#              Globus                       cd:<user_certkey_dir> 
+#                                           cf:<usercert_file>
+#                                           kf:<userkey_file>
+#                                           ad:<authorities_dir>
+#              SSH                          us:<username>
+#              UidGid
+#
+#           The additional keys for UsrPwd specify:
+#              'cp' whether to encrypt the password with a public key (default)
+#                   or not (slighty faster), values are 'yes' or '1' for YES,
+#                   'no' or '0' for NO (case sensitive);
+#
+#           The keys for Globus allow to specify only partial changes of 
+#           the defaults:
+#              'cd' defines the directory containing the user certificate
+#                   and private key files;
+#              'cf' defines the user certificate file
+#              'kf' defines the user private key file
+#              'ad' defines the directory containing credentials for
+#                   recognized Certificate Authorities
+#                   (the CA signing the remote host certificate must have
+#                   an entry here)
+#           All these files and directories can be specified as absolute
+#           paths (starting with '/') or as relative to the getenv("HOME")
+#           directory (starting with '~/') or relative to the local '.globus'
+#           directory. Defaults are:
+#              cd:~/.globus
+#              cf:usercert.pem
+#              kf:userkey.pem
+#              ad:/etc/grid-security/certificates
+#
+#           NB: for all the mentioned keys, there should be NO space between
+#           the key and the value, e.g. 'us: qwerty' will result in 
+#           <username>=""
+#
+#           Example of valid 'method' lines:
+#
+#              default    method  ssh pt:yes us:qwerty
+#              default    method  3 pt:0 
+#              default user asdfgh  method  usrpwd pt:1 ru:no 
+#              lxplus*.cern.ch  method  3 pt:no  ad:certificates
+#              pcepsft43.cern.ch  user poiuyt method globus pt:no \
+#                                 cd:~/CA/HubCA/poiuyt ad:certificates
+#            
+#           The first line specifies that when a SSH authentication is
+#           attempted, the user will be prompted for the remote username,
+#           with 'qwerty' as default. The second line states that for 
+#           Globus the user will not be prompted and the credentials
+#           and related files will be looked for in the default places.
+#           The third line specifies that, for UsrPwd authentication, user
+#           'asdfgh' will get a prompt with default username 'asdfgh' and
+#           that a successful authentication will not be reused
+#           The fourth line tells that for Globus to lxplus, the user 
+#           will still not be prompted, but the credentials for the 
+#           CA signing the remote certificate will be looked
+#           for in ~/.globus/certificates.
+#           The fifth line tells that for Globus authentication on 
+#           pcepsft43 of user poiuyt, the usercert.pem and userkey.pem
+#           files are looked for in directory ~/CA/HubCA/poiuyt, 
+#           and the credentials for the CA signing the remote certificate
+#           in ~/.globus/certificates.
+#            
diff --git a/etc/hostcert.conf b/etc/hostcert.conf
new file mode 100644
index 0000000000000000000000000000000000000000..d18e520535f1c69d4630b79622c8901d9cfe697b
--- /dev/null
+++ b/etc/hostcert.conf
@@ -0,0 +1,7 @@
+# This is a comment ...
+#/etc/grid-security/certificates   /etc/grid-security/hostcert.pem            /etc/grid-security/hostkey.pem  /etc/grid-security/grid-mapfile1
+#/etc/grid-security/certificates   /etc/grid-security/hostcert.pem            /etc/grid-security/hostkey.pem 
+#/etc/grid-security/certificates    /home/ganis/.globus/usercert.pem          /home/ganis/.globus/userkey.pem
+# /etc/grid-security/certificates   /etc/grid-security/cernCA/hostcert.pem     /etc/grid-security/cernCA/hostkey.pem
+# This to try automatic completion ...
+# /home/ganis/.globus/certificates
diff --git a/etc/rpdauth.allow b/etc/rpdauth.allow
new file mode 100644
index 0000000000000000000000000000000000000000..6d71dd05c65e5d6b3f5b031bccfd409319594cd8
--- /dev/null
+++ b/etc/rpdauth.allow
@@ -0,0 +1,79 @@
+#
+#  rpdauth.allow   This file describes the names of the hosts for which
+#                  the allowed authentication methods are not the default ones
+#                  as specified in system.rootc (if any).
+#                  This file is used by the 'rootd' and 'proofd' daemons.
+#
+#  Format:
+#    - lines starting with '#' are comment lines.
+#
+#    - hosts can specified either with their FQDN (eg, pcepsft43.cern.ch) or
+#      their IP address (eg 137.138.99.73).
+#
+#    - the '*' character can be used in the first field of the name to 
+#      indicate a set of machines, e.g. pcepsft*.cern.ch applies to all 
+#      'pcepsft' machines in the domain 'cern.ch'
+#      (to indicate all 'lxplus' machines you should use 'lxplus*.cern.ch'
+#      because internally the generic lxplus machine has a real name of
+#      the form lxplusnnn.cern.ch).
+#
+#    - a whole domain can be indicated by its name, with at least two non 
+#      null fields, eg 'cern.ch' or '.cern.ch' ; '.ch' is not accepted.
+#
+#    - subsets of the IP address can also be used to indicate a set of
+#      machines, however, it is mandatory to end the subset with a '.', 
+#      e.g. '137.138.' is an alternative way to indicate the 'cern.ch'
+#      domain, but '137.138' is invalid because ambiguous.
+#
+#    - the information following the name or IP address indicates, in order
+#      of preference, the short names or the internal codes of authentication 
+#      methods accepted for requests coming from the specified host(s); the 
+#      ones implemented so far are:
+#
+#        Method                           short name   code
+#
+#        UsrPwd                            usrpwd       0
+#        SRP                               srp          1
+#        Kerberos                          krb5         2
+#        Globus                            globus       3
+#        SSH                               ssh          4
+#        UidGid                            uidgid       5   (insecure)
+#
+#     (The insecure method is intended to speed up access within a cluster
+#     protected by other means from outside attacks; should not be used for 
+#     intercluster or interdomain authentication).
+#     Methods non specified explicitly are not accepted. 
+#     For the insecure method it is possible to give access only to a 
+#     specific list of users by specifying the usernames after the method
+#     separated by colons (:) example:
+#
+#        uidgid:user1:user2:user3
+#
+#     will allow uidgid access only to users user1, user2 and user3. 
+#     This is useful to give easy access to data servers.
+#
+#     It is also possible to deny access to a user by using a '-' in front of 
+#     the name:
+#
+#        uidgid:-user4
+#
+#   - Lines ending with '\' are followed by additional information for the 
+#     host on the next line; the name of the host should not be repeated.             
+#
+# Example of allowing machines in the cern.ch domain to authenticate
+# using SSH (as preferred method) followed by the Globus and UsrPwd methods;
+# in this case, attempts to use SRP, Kerberos or UidGid methods will be
+# rejected; however, the accepted methods will be comunicated to the client
+# and an automatic retry is attempted if the client can use any of them
+# (negotiation).
+#
+# Valid examples:
+#
+# default              none
+# default              ssh 0 uidgid
+# 127.0.0.1            4 0 3 1 2 5
+# 137.138.             4 0
+# pceple19.cern.ch     4 1 3 2 5 0
+# lxplus*.cern.ch      4 1 globus 0:ganis:gganis 5  
+# pcepsft43.cern.ch    4 3 1 5 2 0
+# afal57.cern.ch       0 5 4 
diff --git a/globusauth/Module.mk b/globusauth/Module.mk
new file mode 100644
index 0000000000000000000000000000000000000000..1c5b7d0120147b5f1912aba8aef8444e148a4f16
--- /dev/null
+++ b/globusauth/Module.mk
@@ -0,0 +1,67 @@
+# Module.mk for krb5 authentication module
+# Copyright (c) 2002 Rene Brun and Fons Rademakers
+#
+# Author: Fons Rademakers, 18/3/2002 (for krb5auth)
+# Mod by: Gerardo Ganis, 18/1/2003
+
+MODDIR       := globusauth
+MODDIRS      := $(MODDIR)/src
+MODDIRI      := $(MODDIR)/inc
+
+GLBSAUTHDIR  := $(MODDIR)
+GLBSAUTHDIRS := $(GLBSAUTHDIR)/src
+GLBSAUTHDIRI := $(GLBSAUTHDIR)/inc
+
+##### libGlobusAuth #####
+GLBSAUTHH    := $(wildcard $(MODDIRI)/*.h)
+GLBSAUTHS    := $(wildcard $(MODDIRS)/*.cxx)
+GLBSAUTHO    := $(GLBSAUTHS:.cxx=.o)
+
+GLBSAUTHDEP  := $(GLBSAUTHO:.o=.d)
+
+GLBSAUTHLIB  := $(LPATH)/libGlobusAuth.$(SOEXT)
+
+##### experimental patch #####
+GLBPATCHS     :=
+GLBPATCHO     :=
+GLBPATCHDEP   :=
+ifneq ($(GLBPATCHFLAGS),)
+GLBPATCHS     := $(MODDIRS)/globus_gsi_system_config.c
+GLBPATCHO     := $(GLBPATCHS:.c=.o)
+GLBPATCHDEP   := $(GLBPATCHO:.o=.d)
+endif
+
+# used in the main Makefile
+ALLHDRS     += $(patsubst $(MODDIRI)/%.h,include/%.h,$(GLBSAUTHH))
+ALLLIBS     += $(GLBSAUTHLIB)
+
+# include all dependency files
+INCLUDEFILES += $(GLBSAUTHDEP)
+
+##### local rules #####
+include/%.h:    $(GLBSAUTHDIRI)/%.h
+		cp $< $@
+
+$(GLBSAUTHLIB): $(GLBSAUTHO) $(GLBPATCHO) $(MAINLIBS)
+		@$(MAKELIB) $(PLATFORM) $(LD) "$(LDFLAGS)" \
+		   "$(SOFLAGS)" libGlobusAuth.$(SOEXT) $@ "$(GLBSAUTHO) $(GLBPATCHO)" \
+		   "$(GLBSAUTHLIBEXTRA) $(GLOBUSLIBDIR) $(GLOBUSLIB)"
+
+all-globusauth:   $(GLBSAUTHLIB)
+
+clean-globusauth:
+		@rm -f $(GLBSAUTHO)
+
+clean::         clean-globusauth
+
+distclean-globusauth: clean-globusauth
+		@rm -f $(GLBSAUTHDEP) $(GLBSAUTHLIB)
+
+distclean::     distclean-globusauth
+
+##### extra rules ######
+$(GLBSAUTHO): %.o: %.cxx
+	$(CXX) $(OPT) $(CXXFLAGS) -I$(GLOBUSINCDIR) -I$(GLOBUSINCDIR)/gcc32dbg -I$(GLOBUSINCDIR)/gcc32dbgpthr -o $@ -c $<
+
+$(GLBPATCHO): %.o: %.c
+	$(CC) $(OPT) $(CFLAGS) $(GLBPATCHFLAGS) -I$(GLOBUSINCDIR) -I$(GLOBUSINCDIR)/gcc32dbg -I$(GLOBUSINCDIR)/gcc32dbgpthr -o $@ -c $<
diff --git a/globusauth/src/GlobusAuth.cxx b/globusauth/src/GlobusAuth.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..18ca6573f3ac3669d67a6422ab1b1edb9b10c666
--- /dev/null
+++ b/globusauth/src/GlobusAuth.cxx
@@ -0,0 +1,1308 @@
+// @(#)root/globus:$Name:$:$Id:$
+// Author: Gerardo Ganis  15/01/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+/* Parts of this file are adapted from the Globus Tool Kit version 2.2.3
+ * are subject to related licenses.
+ * Please refer to www.globus.org for details
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern "C" {
+#include <globus_gss_assist.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+}
+#include "TSocket.h"
+#include "TAuthenticate.h"
+#include "THostAuth.h"
+#include "TError.h"
+#include "TSystem.h"
+#include "TROOT.h"
+#include "TApplication.h"
+#include "TEnv.h"
+#include "Getline.h"
+#include "rpderr.h"
+static gss_cred_id_t GlbDelCredHandle = GSS_C_NO_CREDENTIAL;
+int gShmIdCred = -1;
+char gConfDir[kMAXPATHLEN] = { 0 };
+static int gLocalCallEnv = -1;
+char gUser[256] = { 0 };
+
+int GlobusGetDelCred();
+void GlobusCleanup();
+void GlobusError(char *, OM_uint32, OM_uint32, int);
+int GlobusStoreSecContext(char *, gss_ctx_id_t, char *);
+int GlobusGetLocalEnv(int *, TString);
+int GlobusGetNames(int, char **, char **);
+int GlobusGetCredHandle(int, gss_cred_id_t *);
+int GlobusCheckSecContext(char *, char *);
+int GlobusUpdateSecContInfo(int);
+void GlobusSetCertificates(int);
+
+Int_t GlobusAuthenticate(TAuthenticate *, TString &, TString &);
+
+class GlobusAuthInit {
+ public:
+   GlobusAuthInit() {
+      TAuthenticate::SetGlobusAuthHook(&GlobusAuthenticate);
+}};
+static GlobusAuthInit globusauth_init;
+
+// For established Security Contexts
+static char **hostGlbSecCont = 0;
+static char **subjGlbSecCont = 0;
+static gss_ctx_id_t *sptrGlbSecCont = 0;
+static int NumGlbSecCont = 0;
+
+// OffSet in Auth Tab remote file
+TString gDetails;
+static int gNeedProxy = 1;
+char gPromptReUse[20];
+Int_t gPrompt = 0;
+Int_t gRSAKey = 0;
+
+TSocket *sock = 0;
+THostAuth *HostAuth = 0;
+TString protocol;
+
+//______________________________________________________________________________
+Int_t GlobusAuthenticate(TAuthenticate * Auth, TString & user,
+                         TString & details)
+{
+   // Globus authentication code.
+   // Returns 0 in case authentication failed
+   //         1 in case of success
+   //         2 in case of the remote node doesn not seem to support Globus Authentication
+   //         3 in case of the remote node doesn not seem to have certificates for our CA
+
+   int auth = 0, rc;
+   int retval = 0, kind = 0, type = 0, server_auth = 0, brcv = 0, bsnd = 0;
+   gss_cred_id_t GlbCredHandle = GSS_C_NO_CREDENTIAL;
+   gss_ctx_id_t GlbContextHandle = GSS_C_NO_CONTEXT;
+   OM_uint32 MajStat = 0;
+   OM_uint32 MinStat = 0;
+   OM_uint32 GssRetFlags = 0;
+   OM_uint32 GssReqFlags = 0;
+   int GlbTokenStatus = 0;
+   char *isuj = 0;
+   char *ssuj = 0;
+   char *host_subj = 0;
+   gss_buffer_desc OutBuf;
+
+   // From the calling TAuthenticate
+   sock = Auth->GetSocket();
+   HostAuth = Auth->GetHostAuth();
+   protocol = Auth->GetProtocol();
+
+   if (gDebug > 2)
+      Info("GlobusAuthenticate", " enter: %s %s", protocol.Data(),
+           user.Data());
+
+   // If we are called for local cleanup, do it and return ...
+   if (protocol == "cleanup") {
+      GlobusCleanup();
+      return 1;
+   }
+   // Check ReUse
+   Int_t ReUse = 1;
+   if (gSystem->Getenv("AUTHREUSE") != 0 &&
+       !strcmp(gSystem->Getenv("AUTHREUSE"), "0"))
+      ReUse = 0;
+   gPrompt = 0;
+   if (gSystem->Getenv("PROMPTUSER") != 0) {
+      sprintf(gPromptReUse, "pt:%s ru:%d", gSystem->Getenv("PROMPTUSER"),
+              ReUse);
+      if (!strcmp(gSystem->Getenv("PROMPTUSER"), "1"))
+         gPrompt = 1;
+   } else {
+      sprintf(gPromptReUse, "pt:1 ru:%d", ReUse);
+   }
+
+   // The host FQDN ... for debugging
+   const char *hostFQDN = sock->GetInetAddress().GetHostName();
+
+   // Determine local calling environment ...
+   if ((rc = GlobusGetLocalEnv(&gLocalCallEnv, protocol))) {
+      Error("GlobusAuthenticate",
+            "PROOF Master: unable to set relevant environment variables (rc=%d)",
+            rc);
+      return -1;
+   }
+   if (gDebug > 3)
+      Info("GlobusAuthenticate", " gLocalCallEnv is %d", gLocalCallEnv);
+
+   // Set local certificates according to user requests ...
+   GlobusSetCertificates(gLocalCallEnv);
+
+   // Now we send to the rootd/proofd daemons the issuer name of our globus certificates ..
+   // We get it the x509 relevant certificate ... the location depends on the calling environment
+   char *stmp;
+   if ((rc = GlobusGetNames(gLocalCallEnv, &isuj, &stmp))) {
+      Error("GlobusAuthenticate",
+            "PROOF Master: unable to determine relevant names(rc=%d)", rc);
+      return -1;
+   }
+   if (gDebug > 2)
+      Info("GlobusAuthenticate", " Issuer name is %s (%d)", isuj,
+           strlen(isuj));
+   SafeDelete(stmp);
+
+   // Get credential handle ... either genuine or delegated
+   if (GlobusGetCredHandle(gLocalCallEnv, &GlbCredHandle)) {
+      Error("GlobusAuthenticate", "unable to acquire valid credentials");
+      return -1;
+   }
+   if (gDebug > 3)
+      Info("GlobusAuthenticate", " Credential Handle is 0x%x",
+           GlbCredHandle);
+
+   // Inquire credentials for Subject name and convert it in human readable form ...
+   gss_name_t Name;
+   OM_uint32 LifeTime;
+   gss_cred_usage_t CredUsage;
+   gss_OID_set Mech;
+   gss_OID NameType;
+   if ((MajStat =
+        gss_inquire_cred(&MinStat, GlbCredHandle, &Name, &LifeTime,
+                         &CredUsage, &Mech)) != GSS_S_COMPLETE) {
+      GlobusError("GlobusAuthenticate: gss_inquire_cred", MajStat, MinStat,
+                  0);
+      return -1;
+   }
+   if ((MajStat =
+        gss_display_name(&MinStat, Name, &OutBuf,
+                         &NameType)) != GSS_S_COMPLETE) {
+      GlobusError("GlobusAuthenticate: gss_inquire_cred", MajStat, MinStat,
+                  0);
+      return -1;
+   } else {
+      ssuj = StrDup((char *) OutBuf.value);
+   }
+   if (gDebug > 2)
+      Info("GlobusAuthenticate", " Subject name is %s (%d)", ssuj,
+           strlen(ssuj));
+
+   // Create Options string
+   char *Options = new char[strlen(ssuj) + 20];
+   int Opt = ReUse * kAUTH_REUSE_MSK;
+   if (GlobusCheckSecContext((char *) hostFQDN, ssuj) > -1) {
+      sprintf(Options, "%d %d %s", Opt, strlen(ssuj), ssuj);
+   } else {
+      sprintf(Options, "%d 4 None", Opt);
+   }
+
+   // Check established authentications
+   kind = kROOTD_GLOBUS;
+   retval = ReUse;
+   rc = 0;
+   if ((rc =
+        TAuthenticate::AuthExists(Auth, (Int_t) TAuthenticate::kGlobus,
+                                  gDetails, Options, &kind,
+                                  &retval)) == 1) {
+      // A valid authentication exists: we are done ...
+      SafeDelete(Options);
+      return 1;
+   }
+   if (rc == -2) {
+      SafeDelete(Options);
+      return rc;
+   }
+   // If server does not support Globus authentication we can't continue ...
+   if (retval == 0 || kind != kROOTD_GLOBUS) {
+      if (gDebug > 2)
+         Info("GlobusAuthenticate", " got retval: %d kind: %d from server",
+              retval, kind);
+      return 2;
+   }
+   // Now we send the issuer to the server daemon
+   char *buf = new char[20];
+   sprintf(buf, "%d", (int) (strlen(isuj) + 1));
+   if ((bsnd = sock->Send(buf, kMESS_STRING)) != (int) (strlen(buf) + 1)) {
+      Error("GlobusAuthenticate",
+            "Length of Issuer name not send correctly: bytes sent: %d (tot len: %d)",
+            bsnd - 1, strlen(buf));
+      return 0;
+   }
+   SafeDelete(buf);
+   // Now we send it to the server daemon
+   if ((bsnd = sock->Send(isuj, kMESS_STRING)) != (int) (strlen(isuj) + 1)) {
+      Error("GlobusAuthenticate",
+            "Issuer name not send correctly: bytes sent: %d (tot len: %d)",
+            bsnd - 1, strlen(isuj));
+      return 0;
+   }
+   // Now we wait for the replay from the server ...
+   sock->Recv(retval, kind);
+   if (kind != kROOTD_GLOBUS) {
+      Error("GlobusAuthenticate",
+            "recv host subj: unexpected message from daemon: kind: %d (expecting: %d)",
+            kind, kROOTD_GLOBUS);
+   } else {
+      if (retval == 0) {
+         Error("GlobusAuthenticate",
+               "recv host subj: host not able to authenticate this CA");
+         return 3;
+      } else {
+         if (gDebug > 3)
+            Info("GlobusAuthenticate",
+                 "recv host subj: buffer length is: %d", retval);
+         host_subj = new char[retval + 1];
+         brcv = sock->Recv(host_subj, retval, kind);
+         if (brcv < (retval - 1)) {
+            Error("GlobusAuthenticate",
+                  "recv host subj: did not receive all the bytes (recv: %d, due >%d)",
+                  brcv, retval);
+            Error("GlobusAuthenticate", "recv host subj: (%d) %s",
+                  strlen(host_subj), host_subj);
+            return 0;
+         }
+      }
+   }
+   // Now we have a valid subject name for the host ...
+   if (gDebug > 2)
+      Info("GlobusAuthenticate", "Host subject: %s", host_subj);
+
+   // We need to associate a FILE* stream with the socket
+   // It will automatically closed when the socket will be closed ...
+   int SockFd = sock->GetDescriptor();
+   FILE *FILE_SockFd = fdopen(SockFd, "w+");
+
+
+   // Type of request for credentials depend on calling environment
+   GssReqFlags =
+       gLocalCallEnv >
+       0 ? (GSS_C_DELEG_FLAG | GSS_C_MUTUAL_FLAG) : GSS_C_MUTUAL_FLAG;
+   if (gDebug > 3)
+      Info("GlobusAuthenticate",
+           " GssReqFlags: 0x%x, GlbCredentials: 0x%x", GssReqFlags,
+           (int) GlbCredHandle);
+
+   // Now we are ready to start negotiating with the Server
+   if ((MajStat =
+        globus_gss_assist_init_sec_context(&MinStat, GlbCredHandle,
+                                           &GlbContextHandle, host_subj,
+                                           GssReqFlags, &GssRetFlags,
+                                           &GlbTokenStatus,
+                                           globus_gss_assist_token_get_fd,
+                                           (void *) FILE_SockFd,
+                                           globus_gss_assist_token_send_fd,
+                                           (void *) FILE_SockFd)) !=
+       GSS_S_COMPLETE) {
+      GlobusError("GlobusAuthenticate: gss_assist_init_sec_context",
+                  MajStat, MinStat, GlbTokenStatus);
+      SafeDelete(host_subj);
+      return 0;
+   } else {
+      GlobusStoreSecContext((char *) hostFQDN, GlbContextHandle, ssuj);
+      if (gDebug > 2)
+         Info("GlobusAuthenticate", "authenticated to host %s", hostFQDN);
+      if (fflush(FILE_SockFd) != 0) {
+         Warning("GlobusAuthenticate",
+                 "unable to fflush socket: may cause Auth problems on server side\n");
+      }
+      auth = 1;
+   }
+
+   // Now we have the subject and we can release some resources ...
+   SafeDelete(host_subj);
+
+   // Receive username used for login or key request info and type of key
+   int nrec = sock->Recv(retval, type);	// returns user
+
+   if (ReUse == 1) {
+
+      if (type != kROOTD_RSAKEY)
+         Warning("GlobusAuthenticate",
+                 "problems recvn RSA key flag: got message %d, flag: %d",
+                 type, gRSAKey);
+      gRSAKey = 1;
+
+      // RSA key generation (one per session)
+      if (!TAuthenticate::GetRSAInit()) {
+         Auth->GenRSAKeys();
+         TAuthenticate::SetRSAInit();
+      }
+      // Send key
+      if (gDebug > 3)
+         Info("GlobusAuthenticate", "Sending Local Key:\n '%s'",
+              TAuthenticate::GetRSAPubExport());
+      sock->Send(TAuthenticate::GetRSAPubExport(), kROOTD_RSAKEY);
+
+      // Receive username used for login
+      nrec = sock->Recv(retval, type);	// returns user
+   }
+
+   if (type != kROOTD_GLOBUS || retval < 1)
+      Warning("GlobusAuthenticate",
+              "problems recvn (user,offset) length (%d:%d bytes:%d)", type,
+              retval, nrec);
+   char *rfrm = new char[retval + 1];
+   nrec = sock->Recv(rfrm, retval + 1, type);	// returns user
+   if (type != kMESS_STRING)
+      Warning("GlobusAuthenticate",
+              "username and offset not received (%d:%d)", type, nrec);
+   else if (gDebug > 2)
+      Info("GlobusAuthenticate", "logging remotely as %s ", rfrm);
+
+   // Parse answer
+   char *lUser = new char[retval];
+   Int_t OffSet = -1;
+   sscanf(rfrm, "%s %d", lUser, &OffSet);
+
+   // Return username
+   user = lUser;
+   // Keep track of remote login username ...
+   strcpy(gUser, lUser);
+
+   // Receive Token
+   char *Token = 0;
+   if (ReUse == 1 && OffSet > -1) {
+      if (TAuthenticate::SecureRecv(sock, gRSAKey, &Token) == -1) {
+         Warning("SRPAuthenticate",
+                 "Problems secure-receiving Token - may result in corrupted Token");
+      }
+      if (gDebug > 3)
+         Info("GlobusAuthenticate", "received from server: token: '%s' ",
+              Token);
+   } else {
+      Token = StrDup("");
+   }
+
+   // Create and save AuthDetails object
+   TAuthenticate::SaveAuthDetails(Auth, (Int_t) TAuthenticate::kGlobus,
+                                  OffSet, ReUse, gDetails, lUser, gRSAKey,
+                                  Token);
+   details = gDetails;
+
+   // receive status from server
+   sock->Recv(server_auth, kind);
+   if (gDebug > 2)
+      Info("GlobusAuthenticate", "received auth status from server: %d ",
+           server_auth);
+
+   if (auth && !server_auth)
+      Warning("GlobusAuthenticate",
+              " it looks like server did not authenticate ");
+
+   // free allocated memory ...
+   SafeDelete(isuj);
+   SafeDelete(ssuj);
+   SafeDelete(rfrm);
+   SafeDelete(lUser);
+   SafeDelete(Token);
+
+   // return result
+   return auth;
+}
+
+//______________________________________________________________________________
+int GlobusGetDelCred()
+{
+   // This function fetchs from the shared memory segment created by 'proofd'.
+   // the delegated credentials needed to autheticate the slaves ...
+   // The shared memory segment is destroyed.
+
+   struct shmid_ds shm_ds;
+   OM_uint32 MajStat = 0;
+   OM_uint32 MinStat = 0;
+
+   if (gDebug > 2)
+      Info("GlobusGetDelCred:", "Enter ...");
+
+   // Attach segment to address
+   gss_buffer_t databuf = (gss_buffer_t) shmat(gShmIdCred, 0, 0);
+
+   // Import credentials
+   //    credential= (gss_buffer_t)malloc(sizeof(gss_buffer_desc)+databuf->length);
+   gss_buffer_t credential =
+       (gss_buffer_t) new char[sizeof(gss_buffer_desc) + databuf->length];
+   credential->length = databuf->length;
+   credential->value =
+       (void *) ((char *) credential + sizeof(size_t) + sizeof(void *));
+   void *dbufval =
+       (void *) ((char *) databuf + sizeof(size_t) + sizeof(void *));
+   memmove(credential->value, dbufval, credential->length);
+   if ((MajStat =
+        gss_import_cred(&MinStat, &GlbDelCredHandle, 0, 0, credential, 0,
+                        0)) != GSS_S_COMPLETE) {
+      GlobusError("GlobusGetDelCred: gss_import_cred", MajStat, MinStat,
+                  0);
+      return 1;
+   } else if (gDebug > 3)
+      Info("GlobusGetDelCred:",
+           "Globus Credentials successfully imported (0x%x)",
+           GlbDelCredHandle);
+
+   SafeDelete(credential);
+
+   // Detach from shared memory segment
+   int rc = shmdt((const void *) databuf);
+   if (rc != 0) {
+      if (gDebug > 0)
+         Info("GlobusGetDelCred:",
+              "unable to detach from shared memory segment (rc=%d)", rc);
+   }
+   if (gDebug > 3) {
+      rc = shmctl(gShmIdCred, IPC_STAT, &shm_ds);
+      Info("GlobusGetDelCred:",
+           "Process: uid: %d, euid: %d - Buffer: uid: %d, cuid: %d",
+           getuid(), geteuid(), shm_ds.shm_perm.uid, shm_ds.shm_perm.cuid);
+   }
+
+   rc = shmctl(gShmIdCred, IPC_RMID, &shm_ds);
+   if (rc == 0) {
+      if (gDebug > 2)
+         Info("GlobusGetDelCred:",
+              "shared memory segment successfully marked as destroyed");
+   } else {
+      Warning("GlobusGetDelCred:",
+              "unable to mark segment %d as destroyed", gShmIdCred);
+   }
+
+   return 0;
+}
+
+//______________________________________________________________________________
+void GlobusError(char *mess, OM_uint32 majs, OM_uint32 mins, int toks)
+{
+   // Handle error ...
+
+   char *GlbErr;
+
+   if (!globus_gss_assist_display_status_str
+       (&GlbErr, mess, majs, mins, toks)) {
+   } else {
+      GlbErr = new char[kMAXPATHLEN];
+      sprintf(GlbErr, "%s: error messaged not resolved ", mess);
+   }
+   Error(":Error: %s (majst=%d,minst=%d,tokst:%d)", GlbErr, majs, mins,
+         toks);
+
+   SafeDelete(GlbErr);
+}
+
+//______________________________________________________________________________
+int GlobusStoreSecContext(char *host, gss_ctx_id_t context_handle,
+                          char *client_name)
+{
+   // Store relevant info about an established security context for later use.
+   // On success returns number of stored security contexts; 0 otherwise.
+
+   if (gDebug > 2)
+      Info("GlobusStoreSecContext", "Enter: %s", host);
+
+   // Now we can count it
+   NumGlbSecCont++;
+
+   if (NumGlbSecCont > 1) {
+      char **tmph = hostGlbSecCont;
+      char **tmpc = subjGlbSecCont;
+      gss_ctx_id_t *tmps = sptrGlbSecCont;
+
+      hostGlbSecCont = new char *[NumGlbSecCont];
+      subjGlbSecCont = new char *[NumGlbSecCont];
+      sptrGlbSecCont = new gss_ctx_id_t[NumGlbSecCont];
+
+      int i;
+      for (i = 0; i < NumGlbSecCont - 1; i++) {
+         hostGlbSecCont[i] = strdup(tmph[i]);
+         subjGlbSecCont[i] = strdup(tmpc[i]);
+         sptrGlbSecCont[i] = tmps[i];
+
+      }
+
+      hostGlbSecCont[NumGlbSecCont - 1] = strdup(host);
+      subjGlbSecCont[NumGlbSecCont - 1] = strdup(client_name);
+      sptrGlbSecCont[NumGlbSecCont - 1] = context_handle;
+
+      SafeDelete(tmph);
+      SafeDelete(tmpc);
+      SafeDelete(tmps);
+
+   } else {
+
+      hostGlbSecCont = new char *[NumGlbSecCont];
+      subjGlbSecCont = new char *[NumGlbSecCont];
+      sptrGlbSecCont = new gss_ctx_id_t[NumGlbSecCont];
+      hostGlbSecCont[NumGlbSecCont - 1] = strdup(host);
+      subjGlbSecCont[NumGlbSecCont - 1] = strdup(client_name);
+      sptrGlbSecCont[NumGlbSecCont - 1] = context_handle;
+   }
+
+   if (gDebug > 2) {
+      int isave = NumGlbSecCont - 1;
+      Info("GlobusStoreSecContext",
+           "stored new sec context (session: %d, no:%d, ctx_id_t:0x%x) for client %s for host %s",
+           getpid(), NumGlbSecCont, sptrGlbSecCont[isave],
+           subjGlbSecCont[isave], hostGlbSecCont[isave]);
+   }
+
+   return NumGlbSecCont;
+}
+
+//______________________________________________________________________________
+int GlobusGetLocalEnv(int *LocalEnv, TString protocol)
+{
+   // Determines calling environment.
+   // Returns 0 if successful; 1 otherwise.
+
+   int retval = 0;
+
+   // Calling application
+   TApplication *lApp = gROOT->GetApplication();
+   if (gDebug > 2) {
+      int i = 0;
+      for (; i < lApp->Argc(); i++) {
+         Info("GlobusGetLocalEnv", " Application arguments: %d: %s", i,
+              lApp->Argv()[i]);
+      }
+   }
+
+   *LocalEnv = 0;
+   if (lApp != 0) {
+      if (strstr(lApp->Argv()[1], "proof") != 0) {
+         // This is PROOF ... either Master or Slave ...
+         if (gDebug > 3) {
+            Info("GlobusGetLocalEnv",
+                 " PROOF environment, called by the MASTER/SLAVE");
+            Info("GlobusGetLocalEnv",
+                 " String with Pointer to del cred is 0x%x",
+                 GlbDelCredHandle);
+         }
+         *LocalEnv = 2;
+         strncpy(gConfDir, lApp->Argv()[2], strlen(lApp->Argv()[2]) + 1);
+         gShmIdCred = atoi(lApp->Argv()[7]);
+         if (setenv("X509_CERT_DIR", lApp->Argv()[8], 1)) {
+            Error("GlobusGetLocalEnv",
+                  "PROOF Master: unable to set X509_CERT_DIR ");
+            retval = 1;
+         }
+         if (setenv("X509_USER_CERT", lApp->Argv()[9], 1)) {
+            Error("GlobusGetLocalEnv",
+                  "PROOF Master: unable to set X509_USER_CERT ");
+            retval = 2;
+         }
+         if (setenv("X509_USER_KEY", lApp->Argv()[10], 1)) {
+            Error("GlobusGetLocalEnv",
+                  "PROOF Master: unable to set X509_USER_KEY ");
+            retval = 3;
+         }
+      } else {
+         if (strstr(protocol.Data(), "proof") != 0) {
+            if (gDebug > 3)
+               Info("GlobusGetLocalEnv",
+                    " PROOF environment, called by the CLIENT");
+            *LocalEnv = 1;
+         } else if (strstr(protocol.Data(), "root") != 0) {
+            if (gDebug > 3)
+               Info("GlobusGetLocalEnv", " ROOT environment");
+         } else {
+            Warning("GlobusGetLocalEnv",
+                    " Unable to recognize the environment (protocol: %s)-> assume ROOT",
+                    protocol.Data());
+         }
+      }
+   } else {
+      Warning("GlobusGetLocalEnv",
+              " Unable to get pointer to current application -> assume ROOT environment");
+   }
+
+   return retval;
+}
+
+//______________________________________________________________________________
+int GlobusGetNames(int LocalEnv, char **IssuerName, char **SubjectName)
+{
+   // Get Issuer and Client Names from local certificates.
+   // Returns 0 is successfull, 1 otherwise.
+
+   char *usercert_default = "/.globus/usercert.pem";
+   char *cert_file = 0;
+   X509 *xcert = 0;
+
+   if (gDebug > 2)
+      Info("GlobusGetNames", "Enter: LocalEnv: %d", LocalEnv);
+
+   int retval = 0;
+
+   if (LocalEnv == 2) {
+      // We are a Proof master: the location is given by X509_USER_CERT ... if not exit;
+      if (getenv("X509_USER_CERT") != 0) {
+         int lcf = strlen(getenv("X509_USER_CERT"));
+         cert_file = new char[lcf];
+         strncpy(cert_file, getenv("X509_USER_CERT"), lcf + 1);
+      } else {
+         Error("GlobusGetNames",
+               "PROOF Master: host certificate not defined");
+         retval = 1;
+      }
+   } else {
+      // We are a client: determine the location for user certificate ...
+      if (getenv("X509_USER_CERT") != 0) {
+         int lcf = strlen(getenv("X509_USER_CERT"));
+         cert_file = new char[lcf];
+         strncpy(cert_file, getenv("X509_USER_CERT"), lcf + 1);
+      } else {
+         char *userhome = getenv("HOME");
+         cert_file =
+             new char[strlen(userhome) + strlen(usercert_default) + 1];
+         strncpy(cert_file, userhome, strlen(userhome) + 1);
+         strncpy(cert_file + strlen(cert_file), usercert_default,
+                 strlen(usercert_default) + 1);
+      }
+   }
+
+   // Test the existence of the certificate file //
+   if (access(cert_file, F_OK)) {
+      Error("GlobusGetNames", "requested file %s does not exist",
+            cert_file);
+      //     retval= 2;
+      SafeDelete(cert_file);
+      return 2;
+   } else if (access(cert_file, R_OK)) {
+      Error("GlobusGetNames", "no permission to read requested file %s",
+            cert_file);
+      //     retval= 4;
+      SafeDelete(cert_file);
+      return 4;
+   } else if (gDebug > 3) {
+      Info("GlobusGetNames", "File with certificate: %s", cert_file);
+   }
+   // Second: load the certificate ...
+   FILE *fcert = fopen(cert_file, "r");
+   if (fcert == 0 || !PEM_read_X509(fcert, &xcert, 0, 0)) {
+      Error("GlobusGetNames", "Unable to load user certificate ");
+      SafeDelete(cert_file);
+      return 5;
+   }
+   fclose(fcert);
+
+   // Get the issuer name
+   *IssuerName =
+       StrDup(X509_NAME_oneline(X509_get_issuer_name(xcert), 0, 0));
+   // Get the subject name
+   *SubjectName =
+       StrDup(X509_NAME_oneline(X509_get_subject_name(xcert), 0, 0));
+
+   if (gDebug > 2) {
+      Info("GlobusGetNames", "Issuer Name: %s", *IssuerName);
+      Info("GlobusGetNames", "Subject Name: %s", *SubjectName);
+   }
+
+   SafeDelete(cert_file);
+
+   // Now check if there is a proxy file associated with this user
+   int nProxy = 1;
+   gNeedProxy = 1;
+   char proxy_file[256];
+   sprintf(proxy_file, "/tmp/x509up_u%d", getuid());
+ again:
+
+   if (gDebug > 3)
+      Info("GlobusGetNames", "Testing Proxy file: %s", proxy_file);
+
+   if (!access(proxy_file, F_OK) && !access(proxy_file, R_OK)) {
+      // Second: load the proxy certificate ...
+      fcert = fopen(proxy_file, "r");
+      if (fcert == 0 || !PEM_read_X509(fcert, &xcert, 0, 0)) {
+         Error("GlobusGetNames", "Unable to load user proxy certificate ");
+         return 5;
+      }
+      fclose(fcert);
+      // Get proxy names
+      char *ProxyIssuerName =
+          StrDup(X509_NAME_oneline(X509_get_issuer_name(xcert), 0, 0));
+      char *ProxySubjectName =
+          StrDup(X509_NAME_oneline(X509_get_subject_name(xcert), 0, 0));
+      if (gDebug > 3) {
+         Info("GlobusGetNames", "Proxy Issuer Name: %s", ProxyIssuerName);
+         Info("GlobusGetNames", "Proxy Subject Name: %s",
+              ProxySubjectName);
+      }
+
+      if (strstr(ProxyIssuerName, *SubjectName) == ProxyIssuerName) {
+         gNeedProxy = 0;
+         setenv("X509_USER_PROXY", proxy_file, 1);
+         SafeDelete(ProxyIssuerName);
+         SafeDelete(ProxySubjectName);
+         if (gDebug > 3)
+            Info("GlobusGetNames", "Using Proxy file:%s (gNeedProxy:%d)",
+                 getenv("X509_USER_PROXY"), gNeedProxy);
+
+         return retval;
+      } else {
+         sprintf(proxy_file, "/tmp/x509up_u%d.%d", getuid(), nProxy);
+         nProxy++;
+         SafeDelete(ProxyIssuerName);
+         SafeDelete(ProxySubjectName);
+         goto again;
+      }
+   } else {
+      setenv("X509_USER_PROXY", proxy_file, 1);
+      return retval;
+   }
+
+   return retval;
+}
+
+//______________________________________________________________________________
+int GlobusGetCredHandle(int LocalEnv, gss_cred_id_t * CredHandle)
+{
+   // Get Credential Handle, either from scratch, or from delegated info ...
+   // Returns 0 is successfull, 1 otherwise.
+
+   int retval = 0;
+   OM_uint32 MajStat = 0;
+   OM_uint32 MinStat = 0;
+
+   if (gDebug > 2)
+      Info("GlobusGetCredHandle", "Enter: LocalEnv: %d", LocalEnv);
+
+   if (LocalEnv == 2) {
+      // If we are a PROOF Master autheticating vs Slaves we only need to fetch the delegated
+      // credentials from the shared memory segment the first time we are called ...
+      if (GlbDelCredHandle == GSS_C_NO_CREDENTIAL) {
+         if (GlobusGetDelCred()) {
+            Error("GlobusGetCredHandle",
+                  "unable to fetch valid credentials from the shared memory segment");
+            retval = 1;
+            goto exit;
+         }
+      }
+      *CredHandle = GlbDelCredHandle;
+   } else {
+
+      // Inquire Globus credentials:
+      // This is looking to file X509_USER_PROXY for valid a X509 cert
+      // (default /tmp/x509up_u<uid> )
+      if ((gNeedProxy == 1) ||
+          (MajStat =
+           globus_gss_assist_acquire_cred(&MinStat, GSS_C_INITIATE,
+                                          CredHandle)) != GSS_S_COMPLETE) {
+
+         // Check if interactive session
+         TApplication *lApp = gROOT->GetApplication();
+         if (strstr(lApp->Argv()[1], "proof") == 0) {
+
+            if (gDebug > 3)
+               Info("GlobusGetCredHandle",
+                    "Failed to acquire credentials: trying to initialize proxies ...");
+
+            // Try to get credentials with usual command line ...
+            char *GlobusLocation = getenv("GLOBUS_LOCATION");
+            if (GlobusLocation == 0) {
+               Error("GlobusGetCredHandle",
+                     "Please define a valid GLOBUS_LOCATION");
+               retval = 2;
+               goto exit;
+            }
+            // First check if there are special requests for proxy duration ...
+            const char *duration =
+                gEnv->GetValue("Globus.ProxyDuration", "default");
+            char initdur[256] = { 0 };
+            if (strstr(duration, "default") == 0) {
+               sprintf(initdur, "-hours %s", duration);
+            }
+            if (gDebug > 3)
+               Info("GlobusAutheticate", "initdur: %s (%s)", initdur,
+                    duration);
+
+            // ... and for number of bits in key ...
+            const char *keybits =
+                gEnv->GetValue("Globus.ProxyKeyBits", "default");
+            char initbit[256] = { 0 };
+            if (strstr(keybits, "default") == 0) {
+               sprintf(initbit, "-bits %s", keybits);
+            }
+            if (gDebug > 3)
+               Info("GlobusAutheticate", "initbit: %s (%s)", initbit,
+                    keybits);
+
+            // ... and for number of bits in key ...
+            char *usrpxy = getenv("X509_USER_PROXY");
+            char initpxy[256] = { 0 };
+            sprintf(initpxy, "-out %s", usrpxy);
+            if (gDebug > 3)
+               Info("GlobusAutheticate", "initpxy: %s (%s)", initpxy,
+                    usrpxy);
+
+            // ... and environment variables
+            char *cerdir = getenv("X509_CERT_DIR");
+            char *usrcer = getenv("X509_USER_CERT");
+            char *usrkey = getenv("X509_USER_KEY");
+            char initenv[kMAXPATHLEN] = { 0 };
+            sprintf(initenv,
+                    "export X509_CERT_DIR=%s; export X509_USER_CERT=%s; export X509_USER_KEY=%s",
+                    cerdir, usrcer, usrkey);
+
+            // to execute command to initiate the proxies one needs to source the globus shell environment
+            char proxyinit[kMAXPATHLEN] = { 0 };
+            sprintf(proxyinit,
+                    "source $GLOBUS_LOCATION/etc/globus-user-env.sh; %s; grid-proxy-init %s %s %s",
+                    initenv, initdur, initbit, initpxy);
+            if (gDebug > 3)
+               Info("GlobusAutheticate", "Executing: %s", proxyinit);
+            gSystem->Exec(proxyinit);
+
+            //  retry now
+            if ((MajStat =
+                 globus_gss_assist_acquire_cred(&MinStat, GSS_C_INITIATE,
+                                                CredHandle)) !=
+                GSS_S_COMPLETE) {
+               GlobusError("GlobusGetCredHandle: gss_assist_acquire_cred",
+                           MajStat, MinStat, 0);
+               retval = 3;
+               goto exit;
+            }
+         } else {
+            Warning("GlobusGetCredHandle",
+                    "proofserv: cannot prompt for credentials: returning failure");
+            retval = 3;
+            goto exit;
+         }
+      }
+   }
+
+ exit:
+   return retval;
+}
+
+//______________________________________________________________________________
+int GlobusCheckSecContext(char *Host, char *SubjName)
+{
+   // Checks if there is already a valid security context established with
+   // remote host for subject ...
+   // On success returns entry number, -1 otherwise.
+
+   int retval = -1;
+   OM_uint32 MajStat = 0;
+   OM_uint32 MinStat = 0;
+   OM_uint32 GssRetFlags = 0;
+   OM_uint32 GlbContLifeTime = 0;
+
+   if (gDebug > 2) {
+      Info("GlobusCheckSecContext", "contacting host: %s", Host);
+      Info("GlobusCheckSecContext",
+           "we have got %d sec context handles in memory", NumGlbSecCont);
+   }
+
+   if (NumGlbSecCont > 0) {
+      int i;
+      for (i = 0; i < NumGlbSecCont; i++) {
+         if (!strcmp(hostGlbSecCont[i], Host)
+             && !strcmp(subjGlbSecCont[i], SubjName)) {
+            if (gDebug > 3)
+               Info("GlobusCheckSecContext",
+                    "we already have a sec context with host: %s for subj: %s",
+                    Host, SubjName);
+
+            // Check validity of the retrieved context ...
+            int Dum1, Dum2;
+            gss_OID MechType;
+            gss_name_t *TargName = 0, *Name = 0;
+            if (sptrGlbSecCont[i] != 0
+                && sptrGlbSecCont[i] != GSS_C_NO_CONTEXT) {
+               if ((MajStat =
+                    gss_inquire_context(&MinStat, sptrGlbSecCont[i], Name,
+                                        TargName, &GlbContLifeTime,
+                                        &MechType, &GssRetFlags, &Dum1,
+                                        &Dum2)) != GSS_S_COMPLETE) {
+                  GlobusError("GlobusCheckSecContext: gss_inquire_context",
+                              MajStat, MinStat, 0);
+                  GlobusUpdateSecContInfo(i);	// delete it from tables ...
+               } else {
+                  if (gDebug > 3)
+                     Info("GlobusCheckSecContext",
+                          "client (%s) already authenticated from host %s (remaining lifetime: %d sec)",
+                          SubjName, Host, GlbContLifeTime);
+                  retval = i;
+               }
+            }
+         }
+      }
+   }
+   return retval;
+}
+
+//______________________________________________________________________________
+int GlobusUpdateSecContInfo(int entry)
+{
+   // Removes entries corresponding to expired, unvalid or deleted security
+   // context. If entry=0 check the validity; if entry>0 remove 'entry'
+   // without checking. Returns number of valid sec contexts established.
+
+   OM_uint32 MajStat = 0;
+   OM_uint32 MinStat = 0;
+   OM_uint32 GssRetFlags = 0;
+   OM_uint32 GlbContLifeTime = 0;
+   int nGoodCont = 0;
+   char **Hosts = new char *[NumGlbSecCont];
+   char **Clien = new char *[NumGlbSecCont];
+   gss_ctx_id_t *SCPtr = new gss_ctx_id_t[NumGlbSecCont];
+
+   if (gDebug > 2)
+      Info("GlobusUpdateSecContInfo", "Enter: entry: %d", entry);
+
+   int i;
+   for (i = 0; i < NumGlbSecCont; i++) {
+      if (entry == 0) {
+         int Dum1, Dum2;
+         gss_OID MechType;
+         gss_name_t *TargName = 0, *client_name = 0;
+
+         // Check validity of the retrieved context ...
+         if (sptrGlbSecCont[i] != 0
+             && sptrGlbSecCont[i] != GSS_C_NO_CONTEXT) {
+            if ((MajStat =
+                 gss_inquire_context(&MinStat, sptrGlbSecCont[i],
+                                     client_name, TargName,
+                                     &GlbContLifeTime, &MechType,
+                                     &GssRetFlags, &Dum1,
+                                     &Dum2)) != GSS_S_COMPLETE) {
+               GlobusError("GlobusUpdateSecContInfo: gss_inquire_context",
+                           MajStat, MinStat, 0);
+            } else {
+               // This is a valid one ...
+               Hosts[nGoodCont] = strdup(hostGlbSecCont[i]);
+               Clien[nGoodCont] = strdup(subjGlbSecCont[i]);
+               SCPtr[nGoodCont] = sptrGlbSecCont[i];
+               nGoodCont++;
+            }
+         }
+      } else if (entry != i) {
+         Hosts[nGoodCont] = strdup(hostGlbSecCont[i]);
+         Clien[nGoodCont] = strdup(subjGlbSecCont[i]);
+         SCPtr[nGoodCont] = sptrGlbSecCont[i];
+         nGoodCont++;
+      }
+   }
+
+   // Update reference table
+   SafeDelete(hostGlbSecCont);
+   SafeDelete(subjGlbSecCont);
+   SafeDelete(sptrGlbSecCont);
+   NumGlbSecCont = nGoodCont;
+
+   if (NumGlbSecCont > 0) {
+
+      if (gDebug > 3)
+         Info("GlobusUpdateSecContInfo",
+              " %d valid established security contexts found");
+
+      hostGlbSecCont = new char *[NumGlbSecCont];
+      subjGlbSecCont = new char *[NumGlbSecCont];
+      sptrGlbSecCont = new gss_ctx_id_t[NumGlbSecCont];
+
+      for (i = 0; i < NumGlbSecCont; i++) {
+         hostGlbSecCont[i] = strdup(Hosts[i]);
+         subjGlbSecCont[i] = strdup(Clien[i]);
+         sptrGlbSecCont[i] = SCPtr[i];
+         if (gDebug > 3)
+            Info("GlobusUpdateSecContInfo",
+                 "Sec cont %d for subject %s with host %s", i, Clien[i],
+                 Hosts[i]);
+      }
+   } else if (gDebug > 3) {
+      Info("GlobusUpdateSecContInfo",
+           "No valid established security contexts remains");
+   }
+
+   return nGoodCont;
+}
+
+//______________________________________________________________________________
+void GlobusSetCertificates(int LocalEnv)
+{
+   // Defines certificate and key files to use, inquiring the client if needed.
+
+   char *userhome = getenv("HOME");
+   char *globusdef = ".globus";
+   char *details = 0;
+   Int_t nr, i;
+   TApplication *lApp = gROOT->GetApplication();
+
+   if (gDebug > 2)
+      Info("GlobusSetCertificates", "Enter: LocalEnv: %d", LocalEnv);
+
+   gDetails = "";
+
+   if (LocalEnv < 2) {
+
+      char temp[kMAXPATHLEN] = { 0 };
+
+      // Defaults
+      char tmpvar[4][kMAXPATHLEN];
+      char *ddir = 0, *dcer = 0, *dkey = 0, *dadi = 0;
+      if (getenv("DEFAULTUSER") != 0) {
+         details = getenv("DEFAULTUSER");
+      } else {
+         details =
+             "cd:~/.globus cf:usercert.pem kf:userkey.pem ad:/etc/grid-security/certificates";
+      }
+
+      if (gDebug > 3)
+         Info("GlobusSetCertificates", " details : %s", details);
+
+      nr = sscanf(details, "%s %s %s %s", tmpvar[0], tmpvar[1], tmpvar[2],
+                  tmpvar[3]);
+      for (i = 0; i < nr; i++) {
+         if (!strncmp(tmpvar[i], "cd:", 3) || !strncmp(tmpvar[i], "Cd:", 3)
+             || !strncmp(tmpvar[i], "cD:", 3)
+             || !strncmp(tmpvar[i], "CD:", 3))
+            ddir = StrDup(tmpvar[i] + 3);
+         if (!strncmp(tmpvar[i], "cf:", 3) || !strncmp(tmpvar[i], "Cf:", 3)
+             || !strncmp(tmpvar[i], "cF:", 3)
+             || !strncmp(tmpvar[i], "CF:", 3))
+            dcer = StrDup(tmpvar[i] + 3);
+         if (!strncmp(tmpvar[i], "kf:", 3) || !strncmp(tmpvar[i], "Kf:", 3)
+             || !strncmp(tmpvar[i], "kF:", 3)
+             || !strncmp(tmpvar[i], "KF:", 3))
+            dkey = StrDup(tmpvar[i] + 3);
+         if (!strncmp(tmpvar[i], "ad:", 3) || !strncmp(tmpvar[i], "Ad:", 3)
+             || !strncmp(tmpvar[i], "aD:", 3)
+             || !strncmp(tmpvar[i], "AD:", 3))
+            dadi = StrDup(tmpvar[i] + 3);
+      }
+      if (ddir == 0)
+         ddir = StrDup("~/.globus");
+      if (dcer == 0)
+         dcer = StrDup("usercert.pem");
+      if (dkey == 0)
+         dkey = StrDup("userkey.pem");
+      if (dadi == 0)
+         dadi = StrDup("/etc/grid-security/certificates");
+
+      // Check if needs to prompt the client
+      char *det = 0;
+      if (gPrompt) {
+         char *dets = 0;
+         if (strstr(lApp->Argv()[1], "proof") == 0) {
+            dets =
+                Getline(Form
+                        (" Local Globus Certificates (%s)\n Enter <key>:<new value> to change: ",
+                         details));
+         } else {
+            Warning("GlobusSetCertificate",
+                    "proofserv: cannot prompt for info");
+         }
+         if (dets && dets[0]) {
+            dets[strlen(dets) - 1] = '\0';	// get rid of \n
+            det = new char[strlen(dets)];
+            strcpy(det, dets);
+         } else
+            det = "";
+
+         if (gDebug > 3)
+            Info("GlobusSetCertificates", "got det: %s (%d)", det,
+                 strlen(det));
+
+      } else {
+         det = "";
+      }
+
+      if (strlen(det) > 0) {
+
+         nr = sscanf(det, "%s %s %s %s", tmpvar[0], tmpvar[1], tmpvar[2],
+                     tmpvar[3]);
+         for (i = 0; i < nr; i++) {
+            if (!strncmp(tmpvar[i], "cd:", 3)
+                || !strncmp(tmpvar[i], "Cd:", 3)
+                || !strncmp(tmpvar[i], "cD:", 3)
+                || !strncmp(tmpvar[i], "CD:", 3)) {
+               if (ddir != 0)
+                  SafeDelete(ddir);
+               ddir = StrDup(tmpvar[i] + 3);
+            }
+            if (!strncmp(tmpvar[i], "cf:", 3)
+                || !strncmp(tmpvar[i], "Cf:", 3)
+                || !strncmp(tmpvar[i], "cF:", 3)
+                || !strncmp(tmpvar[i], "CF:", 3)) {
+               if (dcer != 0)
+                  SafeDelete(dcer);
+               dcer = StrDup(tmpvar[i] + 3);
+            }
+            if (!strncmp(tmpvar[i], "kf:", 3)
+                || !strncmp(tmpvar[i], "Kf:", 3)
+                || !strncmp(tmpvar[i], "kF:", 3)
+                || !strncmp(tmpvar[i], "KF:", 3)) {
+               if (dkey != 0)
+                  SafeDelete(dkey);
+               dkey = StrDup(tmpvar[i] + 3);
+            }
+            if (!strncmp(tmpvar[i], "ad:", 3)
+                || !strncmp(tmpvar[i], "Ad:", 3)
+                || !strncmp(tmpvar[i], "aD:", 3)
+                || !strncmp(tmpvar[i], "AD:", 3)) {
+               if (dadi != 0)
+                  SafeDelete(dadi);
+               dadi = StrDup(tmpvar[i] + 3);
+            }
+         }
+      }
+      // Build gDetails
+      temp[0] = '\0';
+      sprintf(temp, "%s cd:%s cf:%s kf:%s ad:%s", gPromptReUse, ddir, dcer,
+              dkey, dadi);
+      gDetails = temp;
+
+      // Perform "~" expansion ... or allow for paths relative to .globus
+      if (!strncmp(ddir, "~/", 2)) {
+         temp[0] = '\0';
+         sprintf(temp, "%s%s", userhome, ddir + 1);
+         if (ddir != 0)
+            SafeDelete(ddir);
+         ddir = StrDup(temp);
+      } else if (strncmp(ddir, "/", 1)) {
+         temp[0] = '\0';
+         sprintf(temp, "%s/%s/%s", userhome, globusdef, ddir);
+         if (ddir != 0)
+            SafeDelete(ddir);
+         ddir = StrDup(temp);
+      }
+      if (!strncmp(dcer, "~/", 2)) {
+         temp[0] = '\0';
+         sprintf(temp, "%s%s", userhome, dcer + 1);
+         if (dcer != 0)
+            SafeDelete(dcer);
+         dcer = StrDup(temp);
+      } else if (strncmp(dcer, "/", 1)) {
+         temp[0] = '\0';
+         sprintf(temp, "%s/%s", ddir, dcer);
+         if (dcer != 0)
+            SafeDelete(dcer);
+         dcer = StrDup(temp);
+      }
+      if (!strncmp(dkey, "~/", 2)) {
+         temp[0] = '\0';
+         sprintf(temp, "%s%s", userhome, dkey + 1);
+         if (dkey != 0)
+            SafeDelete(dkey);
+         dkey = StrDup(temp);
+      } else if (strncmp(dkey, "/", 1)) {
+         temp[0] = '\0';
+         sprintf(temp, "%s/%s", ddir, dkey);
+         if (dkey != 0)
+            SafeDelete(dkey);
+         dkey = StrDup(temp);
+      }
+      if (!strncmp(dadi, "~/", 2)) {
+         temp[0] = '\0';
+         sprintf(temp, "%s%s", userhome, dadi + 1);
+         if (dadi != 0)
+            SafeDelete(dadi);
+         dadi = StrDup(temp);
+      } else if (strncmp(dadi, "/", 1)) {
+         temp[0] = '\0';
+         sprintf(temp, "%s/%s/%s", userhome, globusdef, dadi);
+         if (dadi != 0)
+            SafeDelete(dadi);
+         dadi = StrDup(temp);
+      }
+      if (gDebug > 3)
+         Info("GlobusSetCertificates", "after expansion: %s %s %s", dcer,
+              dkey, dadi);
+
+      // Save them
+      setenv("X509_CERT_DIR", dadi, 1);
+      setenv("X509_USER_CERT", dcer, 1);
+      setenv("X509_USER_KEY", dkey, 1);
+
+      // Release allocated memory
+      if (ddir != 0)
+         SafeDelete(ddir);
+      if (dcer != 0)
+         SafeDelete(dcer);
+      if (dkey != 0)
+         SafeDelete(dkey);
+      if (dadi != 0)
+         SafeDelete(dadi);
+
+   }
+
+   return;
+}
+
+//______________________________________________________________________________
+void GlobusCleanup()
+{
+   // This function cleans up any stuff related to Globus, releasing
+   // credentials, security contexts and allocated memory ...
+
+   if (gDebug > 2)
+      Info("GlobusCleanup:", "cleaning up local Globus stuff ...");
+
+   if (NumGlbSecCont == 0) {
+      if (gDebug > 3)
+         Info("GlobusCleanup:", "Globus never used: nothing to clean");
+      return;
+   }
+
+   int status = 0;
+   OM_uint32 MajStat = 0;
+   OM_uint32 MinStat = 0;
+
+
+   // Now we can delete the sec context */
+   int i;
+   for (i = 0; i < NumGlbSecCont; i++) {
+      if ((MajStat =
+           gss_delete_sec_context(&MinStat, sptrGlbSecCont + i,
+                                  GSS_C_NO_BUFFER)) != GSS_S_COMPLETE) {
+         GlobusError("GlobusCleanup: gss_delete_sec_context", MajStat,
+                     MinStat, 0);
+         status = 1;
+      }
+   }
+
+   // Release memory allocated for security contexts ...
+   SafeDelete(hostGlbSecCont);
+   SafeDelete(subjGlbSecCont);
+   SafeDelete(sptrGlbSecCont);
+   NumGlbSecCont = 0;
+
+   // Finally check if the shm for imported stuff has not yet been destroyed ...
+   // Recall the shm_id first ...
+   TApplication *lApp = gROOT->GetApplication();
+
+   if (lApp != 0) {
+      if (strstr(lApp->Argv()[1], "proof") != 0) {
+         struct shmid_ds shm_ds;
+         int rc;
+         // Delegated Credentials
+         gShmIdCred = (lApp->Argc() > 6) ? atoi(lApp->Argv()[7]) : -1;
+         if (gShmIdCred != -1) {
+            if ((rc = shmctl(gShmIdCred, IPC_RMID, &shm_ds)) != 0) {
+               if ((rc == EINVAL) || (rc == EIDRM)) {
+                  if (gDebug > 3)
+                     Info("GlobusCleanup:",
+                          "credentials shared memory segment already marked as destroyed");
+               } else {
+                  Warning("GlobusCleanup:",
+                          "unable to mark segment as destroyed (error: 0x%x)",
+                          rc);
+               }
+            } else if (gDebug > 3)
+               Info("GlobusCleanup:",
+                    "shared memory segment %d marked for destruction",
+                    gShmIdCred);
+         } else if (gDebug > 3) {
+            Info("GlobusCleanup:",
+                 "gShmIdCred not defined in this session");
+         }
+      }
+   }
+}
diff --git a/globusauth/src/globus_gsi_system_config.c b/globusauth/src/globus_gsi_system_config.c
new file mode 100644
index 0000000000000000000000000000000000000000..74f231faf840eba8254a2548f2a5700a76e8644b
--- /dev/null
+++ b/globusauth/src/globus_gsi_system_config.c
@@ -0,0 +1,5391 @@
+#ifndef R__GLBCPATCH
+void globus_patch_dummy()
+{
+}
+#else
+
+/* This is the corrected version of 'globus_gsi_system_config.c' 
+ * for a correct behaviour of X509_USER_CERT and X509_USER_KEY
+ * variables in GTK version(s): 2.2.3, 2.2.4, ...
+ * Version 2.0 should be ok.
+ */
+
+#ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
+/**
+ * @file globus_gsi_sysconfig_system_config.c
+ * @author Sam Lang, Sam Meder
+ *
+ * $RCSfile: globus_gsi_system_config.c,v $
+ * $Revision: 1.31 $
+ * $Date: 2002/11/15 02:33:59 $
+ */
+#endif
+
+#include "globus_common.h"
+#include "globus_gsi_system_config.h"
+#include "globus_i_gsi_system_config.h"
+#include "globus_gsi_cert_utils.h"
+#include <openssl/rand.h>
+#include <pwd.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/times.h>
+#include "version.h"
+
+#ifndef DEFAULT_SECURE_TMP_DIR
+#ifndef WIN32
+#define DEFAULT_SECURE_TMP_DIR          "/tmp"
+#else
+#define DEFAULT_SECURE_TMP_DIR          "c:\\tmp"
+#endif
+#endif
+
+#ifndef DEFAULT_EGD_PATH
+#ifndef WIN32
+#define DEFAULT_EGD_PATH                "/tmp"
+#else
+#define DEFAULT_EGD_PATH                "c:\\tmp"
+#endif
+#endif
+
+#ifndef DEFAULT_RANDOM_FILE
+#ifndef WIN32
+#define DEFAULT_RANDOM_FILE             "/tmp"
+#else
+#define DEFAULT_RANDOM_FILE             UNDEFINED_VALUE
+#endif
+#endif
+
+#ifdef WIN32
+#include "winglue.h"
+#include <io.h>
+#else
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <dirent.h>
+#endif
+
+#define X509_CERT_DIR                   "X509_CERT_DIR"
+#define X509_CERT_FILE                  "X509_CERT_FILE"
+#define X509_USER_PROXY                 "X509_USER_PROXY"
+#define X509_USER_CERT                  "X509_USER_CERT"
+#define X509_USER_KEY                   "X509_USER_KEY"
+#define X509_UNIQUE_PROXY_FILE          "x509up_p"
+#define X509_USER_PROXY_FILE            "x509up_u"
+#define SIGNING_POLICY_FILE_EXTENSION   ".signing_policy"
+
+/* This is added after the CA name hash to make the policy filename */
+#define SIGNING_POLICY_FILE_EXTENSION   ".signing_policy"
+
+#ifdef WIN32
+#define FILE_SEPERATOR "\\"
+#define GSI_REGISTRY_DIR                "software\\Globus\\GSI"
+#define X509_DEFAULT_USER_CERT          ".globus\\usercert.pem"
+#define X509_DEFAULT_USER_KEY           ".globus\\userkey.pem"
+#define X509_DEFAULT_PKCS12_FILE        ".globus\\usercred.p12"
+#define X509_DEFAULT_TRUSTED_CERT_DIR   "SLANG: NEEDS TO BE DETERMINED"
+#define X509_INSTALLED_TRUSTED_CERT_DIR "SLANG: NEEDS TO BE DETERMINED"
+#define X509_LOCAL_TRUSTED_CERT_DIR     ".globus\\certificates"
+#define X509_DEFAULT_CERT_DIR           "SLANG: NEEDS TO BE DETERMINED"
+#define X509_INSTALLED_CERT_DIR         "etc"
+#define X509_LOCAL_CERT_DIR             ".globus"
+#define DEFAULT_GRIDMAP                 "SLANG: NEEDS TO BE DETERMINED"
+#define LOCAL_GRIDMAP                   "SLANG: NEEDS TO BE DETERMINED"
+#else
+#define FILE_SEPERATOR                  "/"
+#define X509_DEFAULT_USER_CERT          ".globus/usercert.pem"
+#define X509_DEFAULT_USER_KEY           ".globus/userkey.pem"
+#define X509_DEFAULT_PKCS12_FILE        ".globus/usercred.p12"
+#define X509_DEFAULT_TRUSTED_CERT_DIR   "/etc/grid-security/certificates"
+#define X509_INSTALLED_TRUSTED_CERT_DIR "share/certificates"
+#define X509_LOCAL_TRUSTED_CERT_DIR     ".globus/certificates"
+#define X509_DEFAULT_CERT_DIR           "/etc/grid-security"
+#define X509_INSTALLED_CERT_DIR         "etc"
+#define X509_LOCAL_CERT_DIR             ".globus"
+#define DEFAULT_GRIDMAP                 "/etc/grid-security/grid-mapfile"
+#define INSTALLED_GRIDMAP               "etc/grid-mapfile"
+#define LOCAL_GRIDMAP                   ".gridmap"
+#endif
+
+#define X509_HOST_PREFIX                "host"
+#define X509_CERT_SUFFIX                "cert.pem"
+#define X509_KEY_SUFFIX                 "key.pem"
+
+#define X509_HASH_LENGTH                8
+
+#ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
+
+#define GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR \
+    globus_error_put(globus_error_wrap_errno_error( \
+        GLOBUS_GSI_SYSCONFIG_MODULE, \
+        errno, \
+        GLOBUS_GSI_SYSCONFIG_ERROR_ERRNO, \
+        "%s:%d: Could not allocate enough memory", \
+        __FILE__, __LINE__))
+
+
+int                                     globus_i_gsi_sysconfig_debug_level;
+FILE *                                  globus_i_gsi_sysconfig_debug_fstream;
+
+static int globus_l_gsi_sysconfig_activate(void);
+static int globus_l_gsi_sysconfig_deactivate(void);
+
+int globus_i_gsi_sysconfig_debug_level = 0;
+
+/**
+ * Module descriptor static initializer.
+ */
+globus_module_descriptor_t globus_i_gsi_sysconfig_module =
+{
+    "globus_sysconfig",
+    globus_l_gsi_sysconfig_activate,
+    globus_l_gsi_sysconfig_deactivate,
+    GLOBUS_NULL,
+    GLOBUS_NULL,
+    &local_version
+};
+
+/**
+ * Module activation
+ */
+static
+int
+globus_l_gsi_sysconfig_activate(void)
+{
+    int                                 result = (int) GLOBUS_SUCCESS;
+    const char *                              random_file = NULL;
+    char *                              egd_path = NULL;
+    clock_t                             uptime;
+    struct tms                          proc_times;
+    char                                buffer[200];
+    char *                              tmp_string;
+    static char *                       _function_name_ =
+        "globus_l_gsi_sysconfig_activate";
+
+    tmp_string = getenv("GLOBUS_GSI_SYSCONFIG_DEBUG_LEVEL");
+    if (tmp_string != GLOBUS_NULL)
+    {
+        globus_i_gsi_sysconfig_debug_level = atoi(tmp_string);
+        
+        if ( globus_i_gsi_sysconfig_debug_level < 0)
+        {
+            globus_i_gsi_sysconfig_debug_level = 0;
+        }
+    }
+
+    tmp_string = getenv("GLOBUS_GSI_SYSCONFIG_DEBUG_FILE");
+    if (tmp_string != GLOBUS_NULL)
+    {
+        globus_i_gsi_sysconfig_debug_fstream = fopen(tmp_string, "w");
+        if (globus_i_gsi_sysconfig_debug_fstream == NULL)
+        {
+            result = (int) GLOBUS_FAILURE;
+            goto exit;
+        }
+    }
+    else
+    {
+        /* if the env. var. isn't set, use stderr */
+        globus_i_gsi_sysconfig_debug_fstream = stderr;
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    globus_module_activate(GLOBUS_GSI_CERT_UTILS_MODULE);
+
+    /* OpenSSL's random generator is fed with random
+     * information, which requires system dependant information
+     * (path names)
+     */
+
+    random_file = RAND_file_name(buffer, 200);
+    if (random_file)
+    {
+        RAND_load_file(random_file, 1024L * 1024L);
+    }
+
+    egd_path = getenv("EGD_PATH");
+    if (egd_path == NULL)
+    {
+        egd_path = DEFAULT_EGD_PATH;
+    }
+    RAND_egd(egd_path);
+    
+    if (RAND_status() == 0)
+    {
+        globus_gsi_statcheck_t          status;
+
+        /* this function does a RAND_add based on the
+         * filename - provides platform independence
+         */
+        GLOBUS_GSI_SYSCONFIG_FILE_EXISTS(DEFAULT_RANDOM_FILE, &status);
+
+        /* probably overestimating the entropy in the below */
+        
+        uptime = times(&proc_times);
+        
+        RAND_add((void *) &uptime, sizeof(clock_t), 2);
+        RAND_add((void *) &proc_times, sizeof(struct tms), 8);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_FPRINTF(
+        2, (globus_i_gsi_sysconfig_debug_fstream,
+            "RAND_status = %d", RAND_status()));
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+
+ exit:
+    return result;
+}
+
+/**
+ * Module deactivation
+ *
+ */
+static
+int
+globus_l_gsi_sysconfig_deactivate(void)
+{
+    int                                 result = (int) GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_l_gsi_sysconfig_deactivate";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    RAND_cleanup();
+    globus_module_deactivate(GLOBUS_GSI_CERT_UTILS_MODULE);
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+
+    if (globus_i_gsi_sysconfig_debug_fstream != stderr)
+    {
+        fclose(globus_i_gsi_sysconfig_debug_fstream);
+    }
+
+    return result;
+}
+/* globus_l_gsi_proxy_deactivate() */
+
+
+globus_result_t
+globus_i_gsi_sysconfig_create_cert_dir_string(
+    char **                             cert_dir,
+    char **                             cert_dir_value,
+    globus_gsi_statcheck_t *            status,              
+    const char *                        format,
+    ...)
+{
+    va_list                             ap;
+    globus_result_t                     result;
+
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_create_cert_dir_string";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *cert_dir = NULL;
+
+    va_start(ap, format);
+
+    *cert_dir_value = globus_gsi_cert_utils_v_create_string(format, ap);
+
+    va_end(ap);
+
+    if (*cert_dir_value == NULL)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+     
+    result = GLOBUS_GSI_SYSCONFIG_FILE_EXISTS(*cert_dir_value, status);
+    if (result != GLOBUS_SUCCESS)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR);
+        goto exit;
+    }
+
+    if (format && *status == GLOBUS_FILE_DIR)
+    {
+        *cert_dir = *cert_dir_value;
+    }
+    else if ((*status) != GLOBUS_FILE_DOES_NOT_EXIST)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR,
+            ("%s %s\n",
+             *cert_dir_value, 
+             globus_l_gsi_sysconfig_status_strings[*status]));
+        goto exit;
+    }
+
+
+    result = GLOBUS_SUCCESS;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+    
+
+globus_result_t
+globus_i_gsi_sysconfig_create_cert_string(
+    char **                             cert_string,
+    char **                             cert_string_value,
+    globus_gsi_statcheck_t *            status,
+    const char *                        format,
+    ...)
+{
+    va_list                             ap;
+    globus_result_t                     result;
+    
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_create_cert_string";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *cert_string = NULL;
+
+    va_start(ap, format);
+
+    *cert_string_value = globus_gsi_cert_utils_v_create_string(format, ap);
+
+    va_end(ap);
+
+    if (*cert_string_value == NULL)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+
+    result = GLOBUS_GSI_SYSCONFIG_CHECK_CERTFILE(*cert_string_value, status);
+    if (result != GLOBUS_SUCCESS)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+        goto exit;
+    }
+
+    if (format && (*status) == GLOBUS_FILE_VALID)
+    {
+        *cert_string = *cert_string_value;
+    }
+    else if ((*status) != GLOBUS_FILE_DOES_NOT_EXIST)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+            ("%s %s\n",
+             *cert_string_value, 
+             globus_l_gsi_sysconfig_status_strings[*status]));
+        goto exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+
+globus_result_t
+globus_i_gsi_sysconfig_create_key_string(
+    char **                             key_string,
+    char **                             key_string_value,
+    globus_gsi_statcheck_t *            status,
+    const char *                        format,
+    ...)
+{
+    va_list                             ap;
+    globus_result_t                     result;
+
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_create_key_string";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *key_string = NULL;
+
+    va_start(ap, format);
+
+    *key_string_value = globus_gsi_cert_utils_v_create_string(format, ap);
+    
+    va_end(ap);
+    
+    if (*key_string_value == NULL)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+
+    result = GLOBUS_GSI_SYSCONFIG_CHECK_KEYFILE(*key_string_value, status);
+    if (result != GLOBUS_SUCCESS)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+        goto exit;
+    }
+
+    if (format && (*status) == GLOBUS_FILE_VALID)
+    {
+        *key_string = *key_string_value;
+    }
+    else if ((*status) != GLOBUS_FILE_DOES_NOT_EXIST)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+            ("%s %s\n",
+             *key_string_value,
+             globus_l_gsi_sysconfig_status_strings[*status]));
+        goto exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+
+#endif /* GLOBUS_DONT_DOCUMENT_INTERNAL */
+
+#ifdef WIN32  /* define all the *_win32 functions */
+
+#ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
+
+
+/**
+ * WIN32 - Set Key Permissions
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Set the file permissions of a file to read only by the user
+ * which are the permissions that should be set for all private keys.
+ *
+ * @param filename
+ *
+ * @return
+ *        GLOBUS_SUCCESS or an error object id
+ */
+globus_result_t
+globus_gsi_sysconfig_set_key_permissions_win32(
+    char *                              filename)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    globus_gsi_statcheck_t              status;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_set_key_permissions_win32";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    result = globus_gsi_sysconfig_file_exists_win32(
+        filename,
+        &status);
+    if (result != GLOBUS_SUCCESS)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_SETTING_PERMS);
+        goto exit;
+    }
+
+    if (status != GLOBUS_FILE_VALID ||
+       status != GLOBUS_FILE_DIR)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GIS_SYSCONFIG_ERROR_SETTING_PERMS,
+            ("Invalid file: %s", filename));
+        goto exit;
+    }
+
+#error need to fill this in
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * WIN32 - Get HOME Directory
+ * @ingroup globus_i_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get the HOME directory, currently c:\windows
+ * 
+ * @param home_dir
+ *        The home directory of the current user
+ * @return
+ *        GLOBUS_SUCCESS if no error occured, otherwise
+ *        an error object is returned.
+ */
+globus_result_t
+globus_i_gsi_sysconfig_get_home_dir_win32(
+    char **                             home_dir)
+{
+    globus_result_t                     result;
+
+    const char *                        _function_name_ =
+        "globus_i_gsi_sysconfig_get_home_dir_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *home_dir = "c:\\windows";
+
+    if ((*home_dir) == NULL)
+    {
+        result = GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_HOME_DIR,
+            ("Could not get a home directory for this machine"));
+        goto error_exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+
+ error_exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * WIN32 - File Exists
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Check that the file exists
+ *
+ * @param filename the file to check
+ * @param status   the status of the file
+ *
+ * @return 
+ *        GLOBUS_SUCCESS (even if the file doesn't exist) - in some
+ *        abortive cases an error object identifier is returned
+ */
+globus_result_t
+globus_gsi_sysconfig_file_exists_win32(
+    const char *                        filename,
+    globus_gsi_statcheck_t *            status)
+{
+    globus_result_t                     result;
+    struct stat                         stx;
+
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_file_exists_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    if (stat(filename,&stx) == -1)
+    {
+        switch (errno)
+        {
+          case ENOENT:
+          case ENOTDIR:
+            *status = GLOBUS_DOES_NOT_EXIST;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          case EACCES:
+
+            *status = GLOBUS_BAD_PERMISSIONS;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          default:
+            result = globus_error_put(
+                globus_error_wrap_errno_error(
+                    GLOBUS_GSI_SYSCONFIG_MODULE,
+                    errno,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_ERRNO,
+                    __FILE__":%d:%s: Error getting status of keyfile\n",
+                    __LINE__,
+                    _function_name_));
+            goto exit;
+        }
+    }
+
+    /*
+     * use any stat output as random data, as it will 
+     * have file sizes, and last use times in it. 
+     */
+    RAND_add((void*)&stx, sizeof(stx), 2);
+
+    if (stx.st_size == 0)
+    {
+        *status = GLOBUS_ZERO_LENGTH;
+        result = GLOBUS_SUCCESS;
+        goto exit;
+    }
+
+    *status = GLOBUS_VALID;
+    
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}    
+/* @} */
+
+
+/**
+ * WIN32 - Check File Status for Key
+ * @ingroup globus_i_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * This is a convenience function used to check the status of a 
+ * private key file.  The desired status is only the current user has
+ * ownership and read permissions, everyone else should not be able
+ * to access it.
+ * 
+ * @param filename
+ *        The name of the file to check the status of
+ * @param status
+ *        The status of the file being checked
+ *        see @ref globus_gsi_statcheck_t for possible values
+ *        of this variable 
+ *
+ * @return 
+ *        GLOBUS_SUCCESS if the status of the file was able
+ *        to be determined.  Otherwise, an error object
+ *        identifier
+ *
+ * @see globus_gsi_statcheck_t
+ */
+globus_result_t
+globus_i_gsi_sysconfig_check_keyfile_win32(
+    const char *                        filename,
+    globus_gsi_statcheck_t *            status)
+{
+    struct stat                         stx;
+    globus_result_t                     result;
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_check_keyfile_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    if (stat(filename,&stx) == -1)
+    {
+        switch (errno)
+        {
+          case ENOENT:
+          case ENOTDIR:
+            *status = GLOBUS_DOES_NOT_EXIST;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          case EACCES:
+
+            *status = GLOBUS_BAD_PERMISSIONS;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          default:
+            result = globus_error_put(
+                globus_error_wrap_errno_error(
+                    GLOBUS_GSI_SYSCONFIG_MODULE,
+                    errno,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    __FILE__":%d:%s: Error getting status of keyfile\n",
+                    __LINE__,
+                    _function_name_));
+            goto exit;
+        }
+    }
+
+    /*
+     * use any stat output as random data, as it will 
+     * have file sizes, and last use times in it. 
+     */
+    RAND_add((void*)&stx,sizeof(stx),2);
+
+    if (stx.st_size == 0)
+    {
+        *status = GLOBUS_ZERO_LENGTH;
+        result = GLOBUS_SUCCESS;
+    }
+
+    *status = GLOBUS_VALID;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * WIN32 - Check File Status for Cert
+ * @ingroup globus_i_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * This is a convenience function used to check the status of a 
+ * certificate file.  The desired status is the current user has
+ * ownership and read/write permissions, while group and others only
+ * have read permissions.
+ * 
+ * @param filename
+ *        The name of the file to check the status of
+ * @param status
+ *        The status of the file being checked
+ *        see @ref globus_gsi_statcheck_t for possible values
+ *        of this variable 
+ *
+ * @return 
+ *        GLOBUS_SUCCESS if the status of the file was able
+ *        to be determined.  Otherwise, an error object
+ *        identifier
+ *
+ * @see globus_gsi_statcheck_t
+ */
+globus_result_t
+globus_i_gsi_sysconfig_check_certfile_win32(
+    const char *                        filename,
+    globus_gsi_statcheck_t *            status)
+{
+    globus_result_t                     result;
+    struct stat                         stx;
+
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_check_certfile_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+ 
+    if (stat(filename,&stx) == -1)
+    {
+        switch (errno)
+        {
+          case ENOENT:
+          case ENOTDIR:
+            *status = GLOBUS_DOES_NOT_EXIST;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          case EACCES:
+
+            *status = GLOBUS_BAD_PERMISSIONS;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          default:
+            result = globus_error_put(
+                globus_error_wrap_errno_error(
+                    GLOBUS_GSI_SYSCONFIG_MODULE,
+                    errno,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+                    __FILE__":%d:%s: Error getting status of keyfile\n",
+                    __LINE__,
+                    _function_name_));
+            goto exit;
+        }
+    }
+
+    /*
+     * use any stat output as random data, as it will 
+     * have file sizes, and last use times in it. 
+     */
+    RAND_add((void*)&stx,sizeof(stx),2);
+
+    if (stx.st_size == 0)
+    {
+        *status = GLOBUS_ZERO_LENGTH;
+        result = GLOBUS_SUCCESS;
+    }
+
+    *status = GLOBUS_VALID;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+
+    return result;
+}
+/* @} */
+
+/**
+ * @name WIN32 - Get Current Working Directory
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get the current working directory on a windows system
+ *
+ * @param working_dir
+ *        The working directory to get
+ * @return
+ *        GLOBUS_SUCCESS if no error occurred, otherwise an error object
+ *        ID is returned
+ */
+globus_result_t
+globus_gsi_sysconfig_get_current_working_dir_win32(
+    char **                             working_dir)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ = 
+        "globus_gsi_sysconfig_get_current_working_dir_win32";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+#error /* this needs to be filled in */
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * @name WIN32 - Make Absolute Path
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Make the filename into an absolute path string based
+ * on the current working directory.
+ *
+ * @param filename
+ *        the filename to get the absolute path of.  
+ * @param absolute_path
+ *        The resulting absolute path
+ * @return
+ *        GLOBUS_SUCCESS if no error occurred, otherwise
+ *        an error object ID is returned
+ */
+globus_result_t
+globus_gsi_sysconfig_make_absolute_path_for_filename_win32(
+    char *                              filename,
+    char **                             absolute_path)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_make_absolute_path_for_filename_win32";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+    
+#error /* this needs to be filled in */
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * @name WIN32 - Split Directory and Filename
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Split the directory and filename portions of a filename string
+ * into two separate strings
+ *
+ * @param full_filename
+ * @param dir_string
+ * @param filename_string
+ *
+ * @return
+ */
+globus_result_t
+globus_gsi_sysconfig_split_dir_and_filename_win32(
+    char *                              full_filename,
+    char **                             dir_string,
+    char **                             filename_string)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_split_dir_and_filename_win32";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+#error /* this needs to be filled in */
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * WIN32 - Get User ID
+ * @ingroup globus_i_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get a unique string representing the current user.  
+ * On Windows, SLANG: NOT DETERMINED
+ */
+globus_result_t
+globus_gsi_sysconfig_get_user_id_string_win32(
+    char **                             user_id_string)
+{
+    int                                 uid;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_user_id_string_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    result = globus_gsi_sysconfig_get_username_win32(user_id_string);
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    
+    return GLOBUS_SUCCESS;
+}
+/* @} */
+
+/**
+ * WIN32 - Get Username
+ * @ingroup globus_i_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get the username of the current user.  
+ * On Windows, SLANG: NOT DETERMINED
+ */
+globus_result_t
+globus_gsi_sysconfig_get_username_win32(
+    char **                             username)
+{
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_username_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+#error /* SLANG: need to set the string to the username or whatever */
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    
+    return GLOBUS_SUCCESS;
+}
+/* @} */
+
+/**
+ * WIN32 - Get Process ID
+ * @ingroup globus_i_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get a unique string representing the current process.  
+ * On Windows, SLANG: NOT DETERMINED
+ */
+globus_result_t
+globus_gsi_sysconfig_get_proc_id_string_win32(
+    char **                             proc_id_string)
+{
+    int                                 uid;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_proc_id_string_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+#error /* SLANG: need to set the string to the process name or whatever */
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    
+    return GLOBUS_SUCCESS;
+}
+/* @} */
+
+#endif
+
+/**
+ * WIN32 - Get Trusted CA Cert Dir
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get the Trusted Certificate Directory containing the trusted
+ * Certificate Authority certificates.  This directory is determined
+ * in the order shown below.  Failure in one method results in attempting
+ * the next.
+ *
+ * <ol>
+ * <li> <b>X509_CERT_DIR environment variable</b> - if this is set, the
+ * trusted certificates will be searched for in that directory.  This
+ * variable allows the end user to specify the location of trusted
+ * certificates.
+ * <li> <b>"x509_cert_dir" registry key</b> - If
+ * this registry key is set on windows, the directory it points to should
+ * contain the trusted certificates.  The path to the registry key is
+ * software\Globus\GSI
+ * <li> <b>\<user home directory\>\.globus\certificates</b> - If this
+ * directory exists, and the previous methods of determining the trusted
+ * certs directory failed, this directory will be used.  
+ * <li> <b>Host Trusted Cert Dir</b> - This location is intended
+ * to be independant of the globus installation ($GLOBUS_LOCATION), and 
+ * is generally only writeable by the host system administrator.  
+ * SLANG: This value is not currently set for WINDOWS
+ * <li> <b>Globus Install Trusted Cert Dir</b> - this
+ * is $GLOBUS_LOCATION\share\certificates.  
+ * </ol>
+ *
+ * @param cert_dir
+ *        The trusted certificates directory
+ * @return
+ *        GLOBUS_SUCCESS if no error occurred, and a sufficient trusted
+ *        certificates directory was found.  Otherwise, an error object 
+ *        identifier returned.
+ */
+globus_result_t
+globus_gsi_sysconfig_get_cert_dir_win32(
+    char **                             cert_dir)
+{
+    char *                              env_cert_dir = NULL;
+    char *                              val_cert_dir[512];
+    char *                              reg_cert_dir = NULL;
+    char *                              local_cert_dir = NULL;
+    char *                              default_cert_dir = NULL;
+    char *                              installed_cert_dir = NULL;
+    int                                 len;    
+    HKEY                                hkDir = NULL;
+    globus_result_t                     result;
+    char *                              home;
+    char *                              globus_location;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_cert_dir_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *cert_dir = NULL;
+
+    if (getenv(X509_CERT_DIR))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_dir_string(
+            cert_dir, 
+            & env_cert_dir,
+            getenv(X509_CERT_DIR));
+        if (result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR);
+            goto error_exit;
+        }
+    }
+
+    if (!(*cert_dir))
+    {
+        RegOpenKey(HKEY_CURRENT_USER,GSI_REGISTRY_DIR,&hkDir);
+        lval = sizeof(val_cert_dir)-1;
+        if (hkDir && (RegQueryValueEx(hkDir,"x509_cert_dir",0,&type,
+                                      val_cert_dir,&lval) == ERROR_SUCCESS))
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_dir_string(
+                    cert_dir, 
+                    & reg_cert_dir,
+                    val_cert_dir)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+        RegCloseKey(hkDir);
+    }
+
+    /* now check for a trusted CA directory in the user's home directory */
+    if(!(*cert_dir))
+    {
+        if((result = globus_i_gsi_sysconfig_get_home_dir(&home)) != GLOBUS_SUCCESS)
+        {
+            goto error_exit;
+        }
+            
+        if (home) 
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_dir_string(
+                    cert_dir, 
+                    & local_cert_dir,
+                    "%s%s%s",
+                    home,
+                    FILE_SEPERATOR,
+                    X509_LOCAL_TRUSTED_CERT_DIR)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+    }
+
+    /* now look in $GLOBUS_LOCATION/share/certificates */
+    if (!(*cert_dir))
+    {
+        if((result = globus_i_gsi_sysconfig_create_cert_dir_string(
+                cert_dir,
+                & installed_cert_dir,
+                X509_INSTALLED_TRUSTED_CERT_DIR)) != GLOBUS_SUCCESS)
+        {
+            goto error_exit;
+        }
+    }
+
+    /* now check for host based default directory */
+    if (!(*cert_dir))
+    {
+        globus_location = getenv("GLOBUS_LOCATION");
+        
+        if (globus_location)
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_dir_string(
+                    cert_dir,
+                    & default_cert_dir,
+                    "%s%s%s",
+                    globus_location,
+                    FILE_SEPERATOR,
+                    X509_DEFAULT_TRUSTED_CERT_DIR)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_FPRINTF(
+        1, (stderr, "Using cert_dir = %s\n", 
+            (*cert_dir ? *cert_dir : "null")));
+
+    if(!(*cert_dir))
+    {
+        result = globus_error_put(globus_error_construct_string(
+                                      GLOBUS_GSI_SYSCONFIG_MODULE,
+                                      NULL,
+                                      "The trusted certificates directory could not be"
+                                      "found in any of the following locations: \n"
+                                      "1) env. var. X509_CERT_DIR=%s\n"
+                                      "2) registry key x509_cert_dir: %s\n"
+                                      "3) %s\n4) %s\n5) %s\n",
+                                      env_cert_dir,
+                                      reg_cert_dir,
+                                      local_cert_dir,
+                                      installed_cert_dir,
+                                      default_cert_dir));
+
+        goto error_exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+    goto done:
+
+ error_exit:
+    
+    if(*cert_dir)
+    {
+        globus_libc_free(*cert_dir);
+        *cert_dir = NULL;
+    }
+
+ done:
+
+    if(env_cert_dir && (env_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(env_cert_dir);
+    }
+    if(reg_cert_dir && (reg_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(reg_cert_dir);
+    }
+    if(local_cert_dir && (local_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(local_cert_dir);
+    }
+    if(installed_cert_dir && (installed_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(installed_cert_dir);
+    }
+    if(default_cert_dir && (default_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(default_cert_dir);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+
+    return result;
+}
+/* @} */
+
+/**
+ * WIN32 - Get User Certificate Filename
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get the User Certificate Filename based on the current user's
+ * environment.  The following locations are searched for cert and key
+ * files in order:
+ * 
+ * <ol>
+ * <li>environment variables X509_USER_CERT and X509_USER_KEY
+ * <li>registry keys x509_user_cert and x509_user_key in software\Globus\GSI
+ * <li><users home directory>\.globus\usercert.pem and 
+ *     <users home directory>\.globus\userkey.pem
+ * <li><users home directory\.globus\usercred.p12 - this is a PKCS12 credential
+ * </ol>
+ *
+ * @param user_cert
+ *        pointer the filename of the user certificate
+ * @param user_key
+ *        pointer to the filename of the user key
+ * @return
+ *        GLOBUS_SUCCESS if the cert and key files were found in one
+ *        of the possible locations, otherwise an error object identifier
+ *        is returned
+ */
+globus_result_t
+globus_gsi_sysconfig_get_user_cert_filename_win32(
+    char **                             user_cert,
+    char **                             user_key)
+{
+    int                                 len;
+    char *                              home = NULL;
+    char *                              env_user_cert = NULL;
+    char *                              env_user_key = NULL;
+    char *                              reg_user_cert = NULL;
+    char *                              reg_user_key = NULL;
+    char *                              default_user_cert = NULL;
+    char *                              default_user_key = NULL;
+    char *                              default_pkcs12_user_cred = NULL;
+    globus_result_t                     result;
+    HKEY                                hkDir = NULL;
+    char                                val_user_cert[512];
+    char                                val_user_key[512];
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_user_cert_filename_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *user_cert = NULL;
+    *user_key = NULL;
+
+    /* first, check environment variables for valid filenames */
+
+    if(getenv(X509_USER_CERT))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            user_cert,
+            &env_user_cert,
+            getenv(X509_USER_CERT));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto error_exit;
+        }
+    }
+
+    if(getenv(X509_USER_KEY))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            user_key,
+            &env_user_key,
+            getenv(X509_USER_KEY));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTIN_KEY_STRING);
+            goto error_exit;
+        }
+    }
+       
+    /* next, check windows registry keys for valid filenames */
+
+    if(!(*user_cert) || !(*user_key))
+    {
+        RegOpenKey(HKEY_CURRENT_USER,GSI_REGISTRY_DIR,&hkDir);
+        lval = sizeof(val_user_cert)-1;
+        if (hkDir && (RegQueryValueEx(
+                          hkDir,
+                          "x509_user_cert",
+                          0,
+                          &type,
+                          val_user_cert,&lval) == ERROR_SUCCESS))
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    user_cert,
+                    & reg_user_cert,
+                    val_user_cert)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_key_string(
+                   user_key,
+                   & reg_user_key,
+                   val_user_key)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+        RegCloseKey(hkDir);
+    }
+
+
+    /* next, check default locations */
+    if(!(*user_cert) || !(*user_key))
+    {
+        result = GLOBUS_I_GSI_SYSCONFIG_GET_HOME_DIR(&home, &status);
+        if(result == GLOBUS_SUCCESS && status == GLOBUS_FILE_DIR)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_string(
+                user_cert,
+                & default_user_cert,
+                "%s%s%s",
+                home,
+                DEFEAULT_SEPERATOR,
+                X509_DEFAULT_USER_CERT);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_WITH_USER_CERT_FILENAME);
+                goto error_exit;
+            }
+
+            result = globus_i_gsi_sysconfig_create_key_string(
+                key_cert,
+                & default_key_cert,
+                "%s%s%s",
+                home,
+                DEFAULT_SEPERATOR,
+                X509_DEFAULT_USER_KEY);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_WITH_USER_KEY_FILENAME);
+                goto error_exit;
+            }
+        }
+    }
+
+    /* if the cert & key don't exist in the default locations
+     * or those specified by the environment variables, a
+     * pkcs12 cert will be searched for
+     */
+    if(!(*user_cert) || !(*user_key))
+    {
+        if((result = globus_i_gsi_sysconfig_get_home_dir(&home)) == GLOBUS_SUCCESS)
+        {
+            if((result = globus_i_gsi_sysconfig_create_key_string(
+                    user_key,
+                    & default_pkcs12_user_cred,
+                    "%s%s%s",
+                    home,
+                    FILE_SEPERATOR,
+                    X509_DEFAULT_PKCS12_FILE)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+            *user_cert = *user_key;
+        }
+    }
+
+    if(!(*user_cert) || !(*user_key))
+    {
+        result = GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_FILENAME,
+            ("The user cert could not be found in: \n"
+             "1) env. var. X509_USER_CERT=%s\n"
+             "2) registry key x509_user_cert: %s\n"
+             "3) %s\n4) %s\n\n"
+             "The user key could not be found in:\n,"
+             "1) env. var. X509_USER_KEY=%s\n"
+             "2) registry key x509_user_key: %s\n"
+             "3) %s\n4) %s\n",
+             env_user_cert,
+             reg_user_cert,
+             default_user_cert,
+             default_pkcs12_user_cred,
+             env_user_key,
+             reg_user_key,
+             default_user_key,
+             default_pkcs12_user_cred));
+
+        goto error_exit;
+    }
+
+#ifdef DEBUG
+    fprintf(stderr,"Using x509_user_cert=%s\n      x509_user_key =%s\n",
+            (*user_cert) ? (*user_cert) : NULL, 
+            (*user_key) ? (*user_key) : NULL);
+#endif
+
+    result = GLOBUS_SUCCESS;
+    goto done;
+
+ error_exit:
+    
+    if(*user_cert)
+    {
+        globus_libc_free(*user_cert);
+        *user_cert = NULL;
+    }
+    if(*user_key)
+    {
+        globus_libc_free(*user_key);
+        *user_key = NULL;
+    }
+
+ done:
+
+    if(env_user_cert && env_user_cert != (*user_cert))
+    {
+        globus_libc_free(env_user_cert);
+    }
+    if(env_user_key && env_user_key != (*user_key))
+    {
+        globus_libc_free(env_user_key);
+    }
+    if(default_user_cert && default_user_cert != (*user_cert))
+    {
+        globus_libc_free(default_user_cert);
+    }
+    if(default_user_key && default_user_key != (*user_key))
+    {
+        globus_libc_free(default_user_key);
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    
+    return result;
+}
+/* @} */
+
+/**
+ * WIN32 - Get Host Certificate and Key Filenames
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get the Host Certificate and Key Filenames based on the current user's
+ * environment.  The host cert and key are searched for in the following 
+ * locations (in order):
+ *
+ * <ol>
+ * <li>X509_USER_CERT and X509_USER_KEY environment variables
+ * <li>registry keys x509_user_cert and x509_user_key in software\Globus\GSI
+ * <li>SLANG: NOT DETERMINED - this is the default location
+ * <li><GLOBUS_LOCATION>\etc\host[cert|key].pem
+ * <li><users home directory>\.globus\host[cert|key].pem
+ * </ol>
+ * 
+ * @param host_cert
+ *        pointer to the host certificate filename
+ * @param host_key
+ *        pointer to the host key filename
+ *
+ * @return
+ *        GLOBUS_SUCCESS if the host cert and key were found, otherwise
+ *        an error object identifier is returned 
+ */
+globus_result_t
+globus_gsi_sysconfig_get_host_cert_filename_win32(
+    char **                             host_cert,
+    char **                             host_key)
+{
+    int                                 len;
+    char *                              home = NULL;
+    char *                              host_cert = NULL;
+    char *                              host_key = NULL;
+    char *                              env_host_cert = NULL;
+    char *                              env_host_key = NULL;
+    char *                              reg_host_cert = NULL;
+    char *                              reg_host_key = NULL;
+    char *                              default_host_cert = NULL;
+    char *                              default_host_key = NULL;
+    char *                              installed_host_cert = NULL;
+    char *                              installed_host_key = NULL;
+    char *                              local_host_cert = NULL;
+    char *                              local_host_key = NULL;
+    globus_result_t                     result;
+
+    HKEY                                hkDir = NULL;
+    char                                val_host_cert[512];
+    char                                val_host_key[512];
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_host_cert_filename_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *host_cert = NULL;
+    *host_key = NULL;
+
+    /* first check environment variables for valid filenames */
+
+    if(getenv(X509_USER_CERT))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            host_cert,
+            & env_host_cert,
+            getenv(X509_USER_CERT));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto error_exit;
+        }
+    }
+
+    if(getenv(X509_USER_KEY))
+    {
+        result = globus_i_gsi_sysconfig_create_key_string(
+            host_key,
+            & env_host_key,
+            getenv(X509_USER_KEY));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+            goto error_exit;
+        }
+    }
+
+    /* now check the windows registry for valid filenames */
+    if(!(*host_cert) || !(*host_key))
+    {
+        RegOpenKey(HKEY_CURRENT_USER,GSI_REGISTRY_DIR,&hkDir);
+        lval = sizeof(val_host_cert)-1;
+        if (hkDir && (RegQueryValueEx(hkDir,
+                                      "x509_user_cert",
+                                      0,
+                                      &type,
+                                      val_host_cert,
+                                      &lval) == ERROR_SUCCESS))
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    host_cert,
+                    & reg_host_cert,
+                    val_host_cert)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_cert_string(
+                   host_key,
+                   & reg_host_key,
+                   val_host_key)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+        RegCloseKey(hkDir);
+    }
+
+    /* now check default locations for valid filenames */
+    if(!(*host_cert) || !(*host_key))
+    {
+        if((result = globus_i_gsi_sysconfig_get_home_dir(&home)) == GLOBUS_SUCCESS)
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    host_cert,
+                    & default_host_cert,
+                    "%s%s%s%s",
+                    X509_DEFAULT_CERT_DIR,
+                    FILE_SEPERATOR,
+                    X509_HOST_PREFIX,
+                    X509_CERT_SUFFIX)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_key_string(
+                   host_key,
+                   & default_key_cert,
+                   "%s%s%s%s",
+                   X509_DEFAULT_CERT_DIR,
+                   FILE_SEPERATOR,
+                   X509_HOST_PREFIX,
+                   X509_KEY_SUFFIX)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+    }
+
+    /* now check intstalled location for host cert */
+    if(!(*host_cert) || !(*host_key))
+    {
+        globus_location = getenv("GLOBUS_LOCATION");
+
+        if(globus_location)
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    host_cert,
+                    & installed_host_cert,
+                    "%s%s%s%s%s%s",
+                    globus_location,
+                    FILE_SEPERATOR,
+                    X509_INSTALLED_CERT_DIR,
+                    FILE_SEPERATOR,
+                    X509_HOST_PREFIX,
+                    X509_CERT_SUFFIX)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_key_string(
+                   host_key,
+                   & installed_host_key,
+                   "%s%s%s%s%s%s",
+                   globus_location,
+                   FILE_SEPERATOR,
+                   X509_INSTALLED_CERT_DIR,
+                   FILE_SEPERATOR,
+                   X509_HOST_PREFIX,
+                   X509_KEY_SUFFIX)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+    }
+
+    if(!(*host_cert) || !(*host_key))
+    {
+        if(GLOBUS_I_GSI_SYSCONFIG_GET_HOME_DIR(&home) == GLOBUS_SUCCESS)
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    host_cert,
+                    & local_host_cert,
+                    "%s%s%s%s%s%s",
+                    home,
+                    FILE_SEPERATOR,
+                    X509_LOCAL_CERT_DIR,
+                    FILE_SEPERATOR,
+                    X509_HOST_PREFIX,
+                    X509_CERT_SUFFIX)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_key_string(
+                   host_key,
+                   & local_key_cert,
+                   "%s%s%s%s%s%s",
+                   home,
+                   FILE_SEPERATOR,
+                   X509_LOCAL_CERT_DIR,
+                   FILE_SEPERATOR,
+                   X509_HOST_PREFIX,
+                   X509_KEY_SUFFIX)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+    }
+
+#ifdef DEBUG
+    fprintf(stderr,"Using x509_user_cert=%s\n      x509_user_key =%s\n",
+            host_cert, host_key);
+#endif
+
+    if(!(*host_cert) || !(*host_key))
+    {
+        result = GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_FILENAME,
+            ("The user cert could not be found in: \n"
+             "1) env. var. X509_USER_CERT=%s\n"
+             "2) registry key x509_user_cert: %s\n"
+             "3) %s\n4) %s5) %s\n\n"
+             "The user key could not be found in:\n,"
+             "1) env. var. X509_USER_KEY=%s\n"
+             "2) registry key x509_user_key: %s\n"
+             "3) %s\n4) %s5) %s\n",
+             env_host_cert,
+             reg_host_cert,
+             default_host_cert,
+             installed_host_cert,
+             local_host_cert,
+             env_host_key,
+             reg_host_key,
+             default_host_key,
+             installed_host_key,
+             local_host_key));
+
+        goto error_exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+    goto done;
+
+ error_exit:
+
+    if(*host_cert)
+    {
+        globus_libc_free(*host_cert);
+        *host_cert = NULL;
+    }
+    if(*host_key)
+    {
+        globus_libc_free(*host_key);
+        *host_key = NULL;
+    }
+
+ done:
+
+    if(env_host_cert && env_host_cert != *host_cert)
+    {
+        globus_libc_free(env_host_cert);
+    }
+    if(env_host_key && env_host_key != *host_key)
+    {
+        globus_libc_free(env_host_key);
+    }
+    if(reg_host_cert && reg_host_cert != *host_cert)
+    {
+        globus_libc_free(reg_host_cert);
+    }
+    if(reg_host_key && reg_host_key != *host_key)
+    {
+        globus_libc_free(reg_host_key);
+    }
+    if(installed_host_cert && installed_host_cert != *host_cert)
+    {
+        globus_libc_free(installed_host_cert);
+    }
+    if(installed_host_key && installed_host_key != *host_key)
+    {
+        globus_libc_free(installed_host_key);
+    }
+    if(local_host_cert && local_host_cert != *host_cert)
+    {
+        globus_libc_free(local_host_cert);
+    }
+    if(local_host_key && local_host_key != *host_key)
+    {
+        globus_libc_free(local_host_key);
+    }
+    if(default_host_cert && default_host_cert != host_cert)
+    {
+        globus_libc_free(default_host_cert);
+    }
+    if(default_host_key && default_host_key != host_key)
+    {
+        globus_libc_free(default_host_key);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+
+    return result;
+}
+/* @} */
+
+/**
+ * WIN32 - Get Service Certificate and Key Filenames
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get the Service Certificate Filename based on the current user's
+ * environment.  The host cert and key are searched for in the following 
+ * locations (in order):
+ *
+ * <ol>
+ * <li>X509_USER_CERT and X509_USER_KEY environment variables
+ * <li>registry keys x509_user_cert and x509_user_key in software\Globus\GSI
+ * <li>SLANG: NOT DETERMINED - this is the default location
+ * <li>GLOBUS_LOCATION\etc\{service_name}\{service_name}[cert|key].pem
+ *     So for example, if my service was named: myservice, the location
+ *     of the certificate would be: 
+ *     GLOBUS_LOCATION\etc\myservice\myservicecert.pem
+ * <li><users home>\.globus\{service_name}\{service_name}[cert|key].pem
+ * </ol>
+ * 
+ * @param service_name
+ *        The name of the service which allows us to determine the
+ *        locations of cert and key files to look for
+ * @param service_cert
+ *        pointer to the host certificate filename
+ * @param service_key
+ *        pointer to the host key filename
+ *
+ * @return
+ *        GLOBUS_SUCCESS if the service cert and key were found, otherwise
+ *        an error object identifier 
+ */
+globus_result_t
+globus_gsi_sysconfig_get_service_cert_filename_win32(
+    char *                              service_name,
+    char **                             service_cert_filename,
+    char **                             service_key_filename)
+{
+    int                                 len;
+    char *                              home = NULL;
+    char *                              service_cert = NULL;
+    char *                              service_key = NULL;
+    char *                              env_service_cert = NULL;
+    char *                              env_service_key = NULL;
+    char *                              reg_service_cert = NULL;
+    char *                              reg_service_key = NULL;
+    char *                              default_service_cert = NULL;
+    char *                              default_service_key = NULL;
+    char *                              installed_service_cert = NULL;
+    char *                              installed_service_key = NULL;
+    char *                              local_service_cert = NULL;
+    char *                              local_service_key = NULL;
+    globus_result_t                     result;
+
+    HKEY                                hkDir = NULL;
+    char                                val_service_cert[512];
+    char                                val_service_key[512];
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_service_cert_filename_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *service_cert = NULL;
+    *service_key = NULL;
+
+    /* first check environment variables for valid filenames */
+
+    if(getenv(X509_USER_CERT))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            service_cert,
+            &env_service_cert,
+            getenv(X509_USER_CERT));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto error_exit;
+        }
+    }
+
+    if(getenv(X509_USER_KEY))
+    {
+        result = globus_i_gsi_sysconfig_create_key_string(
+            service_key,
+            &env_service_key,
+            getenv(X509_USER_KEY));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+            goto error_exit;
+        }
+    }
+
+    /* now check the windows registry for valid filenames */
+    if(!(*service_cert) || !(*service_key))
+    {
+        RegOpenKey(HKEY_CURRENT_USER,GSI_REGISTRY_DIR,&hkDir);
+        lval = sizeof(val_service_cert)-1;
+        if (hkDir && (RegQueryValueEx(hkDir,
+                                      "x509_user_cert",
+                                      0,
+                                      &type,
+                                      val_service_cert,
+                                      &lval) == ERROR_SUCCESS))
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    service_cert,
+                    & reg_service_cert,
+                    val_service_cert)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_cert_string(
+                   service_key,
+                   & reg_service_key,
+                   val_service_key)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+        RegCloseKey(hkDir);
+    }
+
+
+    /* now check default locations for valid filenames */
+    if(!(*service_cert) || !(*service_key))
+    {
+        if((result = globus_i_gsi_sysconfig_get_home_dir(&home)) == GLOBUS_SUCCESS)
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    service_cert,
+                    & default_service_cert,
+                    "%s%s%s%s%s%s",
+                    X509_DEFAULT_CERT_DIR,
+                    FILE_SEPERATOR,
+                    service_name,
+                    FILE_SEPERATOR,
+                    service_name,
+                    X509_CERT_SUFFIX)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_key_string(
+                   service_key,
+                   & default_key_cert,
+                   "%s%s%s%s%s%s",
+                   X509_DEFAULT_CERT_DIR,
+                   FILE_SEPERATOR,
+                   service_name,
+                   FILE_SEPERATOR,
+                   service_name,
+                   X509_KEY_SUFFIX)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+    }
+
+    /* now check intstalled location for service cert */
+    if(!(*service_cert) || !(*service_key))
+    {
+        globus_location = getenv("GLOBUS_LOCATION");
+
+        if(globus_location)
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    service_cert,
+                    & installed_service_cert,
+                    "%s%s%s%s%s%s%s%s",
+                    globus_location,
+                    FILE_SEPERATOR,
+                    X509_INSTALLED_CERT_DIR,
+                    FILE_SEPERATOR,
+                    service_name,
+                    FILE_SEPERATOR,
+                    service_name,
+                    X509_CERT_SUFFIX)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_key_string(
+                   service_key,
+                   & installed_service_key,
+                   "%s%s%s%s%s%s%s%s",
+                   globus_location,
+                   FILE_SEPERATOR,
+                   X509_INSTALLED_CERT_DIR,
+                   FILE_SEPERATOR,
+                   service_name,
+                   FILE_SEPERATOR,
+                   service_name,
+                   X509_KEY_SUFFIX)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+    }
+
+    if(!(*service_cert) || !(*service_key))
+    {
+        if (home) {
+            free(home);
+            home = NULL;
+        }
+        if(GLOBUS_I_GSI_SYSCONFIG_GET_HOME_DIR(&home) == GLOBUS_SUCCESS)
+        {
+            if((result = globus_i_gsi_sysconfig_create_cert_string(
+                    service_cert,
+                    & local_service_cert,
+                    "%s%s%s%s%s%s%s",
+                    home,
+                    FILE_SEPERATOR,
+                    X509_LOCAL_CERT_DIR,
+                    FILE_SEPERATOR,
+                    service_name,
+                    FILE_SEPERATOR,
+                    service_name,
+                    X509_CERT_SUFFIX)) != GLOBUS_SUCCESS ||
+               (result = globus_i_gsi_sysconfig_create_key_string(
+                   service_key,
+                   & local_key_cert,
+                   "%s%s%s%s%s%s%s%s",
+                   home,
+                   FILE_SEPERATOR,
+                   X509_LOCAL_CERT_DIR,
+                   FILE_SEPERATOR,
+                   service_name,
+                   FILE_SEPERATOR,
+                   service_name,
+                   X509_KEY_SUFFIX)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+    }
+
+#ifdef DEBUG
+    fprintf(stderr,"Using x509_user_cert=%s\n      x509_user_key =%s\n",
+            service_cert, service_key);
+#endif
+
+    if(!(*service_cert) || !(*service_key))
+    {
+        result = GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_FILENAME,
+            ("The user cert could not be found in: \n"
+             "1) env. var. X509_USER_CERT=%s\n"
+             "2) registry key x509_user_cert: %s\n"
+             "3) %s\n4) %s5) %s\n\n"
+             "The user key could not be found in:\n,"
+             "1) env. var. X509_USER_KEY=%s\n"
+             "2) registry key x509_user_key: %s\n"
+             "3) %s\n4) %s5) %s\n",
+             env_service_cert,
+             reg_service_cert,
+             default_service_cert,
+             installed_service_cert,
+             local_service_cert,
+             env_service_key,
+             reg_service_key,
+             default_service_key,
+             installed_service_key,
+             local_service_key));
+
+        goto error_exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+    goto done;
+
+ error_exit:
+
+    if(*service_cert)
+    {
+        globus_libc_free(*service_cert);
+        *service_cert = NULL;
+    }
+    if(*service_key)
+    {
+        globus_libc_free(*service_key);
+        *service_key = NULL;
+    }
+
+ done:
+
+    if(env_service_cert && env_service_cert != *service_cert)
+    {
+        globus_libc_free(env_service_cert);
+    }
+    if(env_service_key && env_service_key != *service_key)
+    {
+        globus_libc_free(env_service_key);
+    }
+    if(reg_service_cert && reg_service_cert != *service_cert)
+    {
+        globus_libc_free(reg_service_cert);
+    }
+    if(reg_service_key && reg_service_key != *service_key)
+    {
+        globus_libc_free(reg_service_key);
+    }
+    if(installed_service_cert && installed_service_cert != *service_cert)
+    {
+        globus_libc_free(installed_service_cert);
+    }
+    if(installed_service_key && installed_service_key != *service_key)
+    {
+        globus_libc_free(installed_service_key);
+    }
+    if(local_service_cert && local_service_cert != *service_cert)
+    {
+        globus_libc_free(local_service_cert);
+    }
+    if(local_service_key && local_service_key != *service_key)
+    {
+        globus_libc_free(local_service_key);
+    }
+    if(default_service_cert && default_service_cert != service_cert)
+    {
+        globus_libc_free(default_service_cert);
+    }
+    if(default_service_key && default_service_key != service_key)
+    {
+        globus_libc_free(default_service_key);
+    }
+    if (home) {
+        free(home);
+        home = NULL;
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+
+    return result;
+}
+/* @} */
+
+/**
+ * WIN32 - Get Proxy Filename
+ * @ingroup globus_gsi_sysconfig_win32
+ */
+/* @{ */
+/**
+ * Get the proxy cert filename based on the following
+ * search order:
+ * 
+ * <ol>
+ * <li> X509_USER_PROXY environment variable - This environment variable
+ * is set by the at run time for the specific application.  If
+ * the proxy_file_type variable is set to GLOBUS_PROXY_OUTPUT
+ *  (a proxy filename for writing is requested), 
+ * and the X509_USER_PROXY is set, this will be the 
+ * resulting value of the user_proxy filename string passed in.  If the
+ * proxy_file_type is set to GLOBUS_PROXY_INPUT and X509_USER_PROXY is 
+ * set, but the file it points to does not exist, 
+ * or has some other readability issues, the 
+ * function will continue checking using the other methods available.
+ * 
+ * <li> check the registry key: x509_user_proxy.  Just as with
+ * the environment variable, if the registry key is set, and proxy_file_type
+ * is GLOBUS_PROXY_OUTPUT, the string set to be the proxy 
+ * filename will be this registry
+ * key's value.  If proxy_file_type is GLOBUS_PROXY_INPUT, and the 
+ * file doesn't exist, the function will check the next method 
+ * for the proxy's filename.
+ * 
+ * <li> Check the default location for the proxy file.  The default
+ * location should be 
+ * set to reside in the temp directory on that host, with the filename
+ * taking the format:  x509_u<user id>
+ * where <user id> is some unique string for that user on the host
+ * </ol>
+ *
+ * @param user_proxy
+ *        the proxy filename of the user
+ *
+ * @return
+ *        GLOBUS_SUCCESS or an error object identifier
+ */
+globus_result_t
+globus_gsi_sysconfig_get_proxy_filename_win32(
+    char **                             user_proxy,
+    globus_gsi_proxy_file_type_t        proxy_file_type)
+{
+    char *                              env_user_proxy = NULL;
+    char *                              env_value = NULL;
+    char *                              default_user_proxy = NULL;
+    char *                              reg_user_proxy = NULL;
+    HKEY                                hkDir = NULL;
+    char                                val_user_proxy[512];
+    int                                 len;
+    globus_result_t                     result;
+    char *                              user_id_string;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_proxy_filename_win32";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *user_proxy = NULL;
+
+    if((env_value = getenv(X509_USER_PROXY)) != NULL &&
+       (result = globus_i_gsi_sysconfig_create_key_string(
+           user_proxy,
+           & env_user_proxy,
+           getenv(X509_USER_PROXY))) != GLOBUS_SUCCESS)
+    {
+        goto error_exit;
+    }
+    
+    /* check if the proxy file type is for writing */
+    if(!(*user_proxy) && env_user_proxy && proxy_file == GLOBUS_PROXY_OUTPUT)
+    {
+        *user_proxy = env_user_proxy;
+    }
+
+    if (!(*user_proxy))
+    {
+        RegOpenKey(HKEY_CURRENT_USER,GSI_REGISTRY_DIR,&hkDir);
+        lval = sizeof(val_user_proxy)-1;
+        if (hkDir && (RegQueryValueEx(hkDir, "x509_user_proxy", 0, &type,
+                                      val_user_proxy, &lval) == ERROR_SUCCESS))
+        {
+            if((result = globus_i_gsi_sysconfig_create_key_string(
+                    proxy_cert,
+                    & reg_user_proxy,
+                    val_user_proxy)) != GLOBUS_SUCCESS)
+            {
+                goto error_exit;
+            }
+        }
+        RegCloseKey(hkDir);
+    }
+
+    if(!(*user_proxy) && reg_user_proxy && proxy_file == GLOBUS_PROXY_OUTPUT)
+    {
+        *user_proxy = reg_user_proxy;
+    }
+
+    if (!user_proxy)
+    {
+        if((result = GLOBUS_GSI_SYSCONFIG_GET_USER_ID_STRING(
+                &user_id_string))
+           != GLOBUS_SUCCESS)
+        {
+            goto error_exit;
+        }
+        if((result = globus_i_gsi_sysconfig_create_key_string(
+                user_proxy,
+                & default_user_proxy,
+                "%s%s%s%s",
+                DEFAULT_SECURE_TMP_DIR,
+                FILE_SEPERATOR,
+                X509_USER_PROXY_FILE,
+                user_id_string)) != GLOBUS_SUCCESS)
+        {
+            goto error_exit;
+        }
+    }
+
+    if(!(*user_proxy) && 
+       default_user_proxy && 
+       proxy_file_type == GLOBUS_PROXY_FILE_OUTPUT)
+    {
+        *user_proxy = default_user_proxy;
+    }
+
+    if(!(*user_proxy))
+    {            
+        result = GLOBUS_GSI_SYSCONFIG_ERROR_RESULT( 
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PROXY_FILENAME,
+            ("A file location for%s the proxy cert could be found in: \n"
+             "1) env. var. X509_USER_PROXY=%s\n"
+             "2) registry key x509_user_proxy: %s\n"
+             "3) %s\n",
+             (proxy_file_type == GLOBUS_PROXY_FILE_INPUT) ? "" : " writing",
+             env_user_proxy,
+             reg_user_proxy,
+             default_user_proxy));
+        
+        goto error_exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+    goto done;
+
+ error_exit:
+    
+    if(*user_proxy)
+    {
+        globus_libc_free(*user_proxy);
+        *user_proxy = NULL;
+    }
+
+ done:
+
+    if(reg_user_proxy && (reg_user_proxy != (*user_proxy)))
+    {
+        globus_libc_free(reg_user_proxy);
+    }
+    if(default_user_proxy && (default_user_proxy != (*default_user_proxy)))
+    {
+        globus_libc_free(default_user_proxy);
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+globus_result_t
+globus_gsi_sysconfig_get_ca_cert_file_win32(
+    char *                              ca_cert_dir,
+    globus_fifo_t *                     ca_cert_list)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_ca_cert_file_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+#error SLANG: need to fill this in
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+
+globus_result_t
+globus_gsi_sysconfig_remove_all_owned_files_win32(
+    char *                              default_filename)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_remove_all_owned_files_win32";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+    
+#error SLANG: need to fill this in
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+
+globus_result_t
+globus_gsi_sysconfig_get_gridmap_filename_win32(
+    char **                             filename)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_gridmap_filename_win32";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+#error SLANG: need to fill this in
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+
+/* END WIN32 SYSCONFIG DEFINITIONS */
+
+#else
+
+/* BEGIN UNIX SYSCONFIG DEFINITIONS */
+
+
+#ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
+
+/**
+ * UNIX - Set Key Permissions
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Set the file permissions of a file to read only by the user
+ * which are the permissions that should be set for all private keys.
+ *
+ * @param filename
+ *
+ * @return
+ *        GLOBUS_SUCCESS or an error object id
+ */
+globus_result_t
+globus_gsi_sysconfig_set_key_permissions_unix(
+    char *                              filename)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    globus_gsi_statcheck_t              status;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_set_key_permissions_unix";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    result = globus_gsi_sysconfig_file_exists_unix(
+        filename,
+        &status);
+    if(result != GLOBUS_SUCCESS)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_SETTING_PERMS);
+        goto exit;
+    }
+
+    if(status != GLOBUS_FILE_VALID &&
+       status != GLOBUS_FILE_DIR)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_SETTING_PERMS,
+            ("Error setting permissions of file: %s %s", 
+             filename,
+             globus_l_gsi_sysconfig_status_strings[status]));
+        goto exit;
+    }
+
+    if(chmod(filename, S_IRUSR|S_IWUSR) < 0)
+    {
+        result = globus_error_put(
+            globus_error_wrap_errno_error(
+                GLOBUS_GSI_SYSCONFIG_MODULE,
+                errno,
+                GLOBUS_GSI_SYSCONFIG_ERROR_SETTING_PERMS,
+                __FILE__":%d:%s: Error setting permissions to "
+                "user read only of file: %s\n", 
+                __LINE__,
+                _function_name_,
+                filename));
+        goto exit;
+    }
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Get User ID
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get a unique string representing the current user.  This is just
+ * the uid converted to a string.  
+ *
+ * @param user_id_string
+ *        A unique string representing the user
+ *
+ * @return
+ *        GLOBUS_SUCCESS unless an error occurred
+ */
+globus_result_t
+globus_gsi_sysconfig_get_user_id_string_unix(
+    char **                             user_id_string)
+{
+    uid_t                               uid;
+    int                                 len;
+    globus_result_t                     result;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_user_id_string_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    uid = getuid();
+    
+    len = globus_libc_printf_length("%d",uid);
+
+    len++;
+
+    if((*user_id_string = malloc(len)) == NULL)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+    
+    globus_libc_snprintf(*user_id_string,len,"%d",uid);
+
+    result = GLOBUS_SUCCESS;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * Unix - Get Username
+ * @ingroup globus_i_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the username of the current user.  
+ */
+globus_result_t
+globus_gsi_sysconfig_get_username_unix(
+    char **                             username)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    struct passwd                       pwd;
+    struct passwd *                     pwd_result;
+    char *                              buf;
+    int                                 buf_len;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_username_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    /* the below seems to be fairly portable */
+    
+    buf_len = sysconf(_SC_GETPW_R_SIZE_MAX) + 1;
+
+    buf = malloc(buf_len);
+
+    if(buf == NULL)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+    
+    if(globus_libc_getpwuid_r(geteuid(),
+                              &pwd,
+                              buf,
+                              buf_len,
+                              &pwd_result) != 0)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PW_ENTRY,
+            ("Error occured for uid: %d",geteuid()));        
+        goto exit;
+    }
+
+    if(pwd_result == NULL || pwd_result->pw_name == NULL)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PW_ENTRY,
+            ("Error occured for uid: %d",geteuid()));        
+        goto exit;        
+    }
+
+    *username = malloc(strlen(pwd_result->pw_name) + 1);
+
+    if(!*username)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+        
+    strncpy(*username, pwd_result->pw_name, 
+            strlen(pwd_result->pw_name) + 1);
+    
+ exit:
+
+    if(buf != NULL)
+    {
+        free(buf);
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Get Process ID
+ * @ingroup globus_i_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get a unique string representing the current process.  This is just
+ * the pid converted to a string.  
+ *
+ * @param proc_id_string
+ *        A unique string representing the process
+ *
+ * @return
+ *        GLOBUS_SUCCESS unless an error occurred
+ */
+globus_result_t
+globus_gsi_sysconfig_get_proc_id_string_unix(
+    char **                             proc_id_string)
+{
+    pid_t                               pid;
+    int                                 len;
+    globus_result_t                     result;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_proc_id_string_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    pid = getpid();
+    
+    len = globus_libc_printf_length("%d",pid);
+
+    len++;
+
+    if((*proc_id_string = malloc(len)) == NULL)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+
+    globus_libc_snprintf(*proc_id_string,len,"%d",pid);
+    
+    result = GLOBUS_SUCCESS;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+#endif
+
+
+/**
+ * @name UNIX - Make Absolute Path
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Make the filename into an absolute path string based
+ * on the current working directory.
+ *
+ * @param filename
+ *        the filename to get the absolute path of.  
+ * @param absolute_path
+ *        The resulting absolute path.  This needs to 
+ *        be freed when no longer needed.
+ * @return
+ *        GLOBUS_SUCCESS if no error occurred, otherwise
+ *        an error object ID is returned
+ */
+globus_result_t
+globus_gsi_sysconfig_make_absolute_path_for_filename_unix(
+    char *                              filename,
+    char **                             absolute_path)
+{
+    int                                 length;
+    char *                              cwd = NULL;
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_make_absolute_path_for_filename_unix";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    if(filename[0] != '/')
+    {
+        result = GLOBUS_GSI_SYSCONFIG_GET_CURRENT_WORKING_DIR(&cwd);
+        if(result != GLOBUS_SUCCESS)
+        {
+            cwd = NULL;
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CWD);
+            goto exit;
+        }
+
+        length = strlen(cwd) + strlen(filename) + 2;
+
+        *absolute_path = malloc(length);
+        if(!*absolute_path)
+        {
+            result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+            goto exit;
+        }
+        globus_libc_snprintf(*absolute_path, length, "%s/%s", cwd, filename);
+    }
+    else
+    {
+        length = strlen(filename) + 1;
+
+        *absolute_path = malloc(length);
+        if(!*absolute_path)
+        {
+            result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+            goto exit;
+        }
+        globus_libc_snprintf(*absolute_path, length, "%s", filename);
+    }
+
+ exit:
+
+    if(cwd != NULL)
+    {
+        free(cwd);
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+
+/**
+ * @name WIN32 - Split Directory and Filename
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Split the directory and filename portions of a filename string
+ * into two separate strings
+ *
+ * @param full_filename
+ *        The filename to split.  Splits on the last occurrance of '/'
+ *        where the directory is everything before the last '/', and
+ *        the filename is everything after.
+ * @param dir_string  
+ *        The directory portion of the filename string.  If no '/' is found
+ *        throughout the string, this variable points to NULL.
+ *        This needs to be freed when no longer needed.
+ * @param filename_string
+ *        The filename portion of the filename string.  If no '/' is found
+ *        throughout, this variable is a duplicate of the full_filename 
+ *        parameter.  This needs to be freed when no longer needed.
+ *
+ * @return
+ *        GLOBUS_SUCCESS if no error occurred.  Otherwise an error object ID
+ *        is returned.
+ */
+globus_result_t
+globus_gsi_sysconfig_split_dir_and_filename_unix(
+    char *                              full_filename,
+    char **                             dir_string,
+    char **                             filename_string)
+{
+    int                                 dir_string_length;
+    int                                 filename_string_length;
+    char *                              split_index = NULL;
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_split_dir_and_filename_unix";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *dir_string = NULL;
+    *filename_string = NULL;
+
+    split_index = strrchr(full_filename, '/');
+    if(!split_index)
+    {
+        *dir_string = NULL;
+        filename_string_length = strlen(full_filename) + 1;
+        *filename_string = malloc(filename_string_length);
+        if(!*filename_string)
+        {
+            result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+            goto exit;
+        }
+
+        globus_libc_snprintf(*filename_string, filename_string_length, 
+                             "%s", full_filename); 
+    }
+    else
+    {
+        dir_string_length = split_index - full_filename + 1;
+        
+        *dir_string = malloc(dir_string_length);
+        
+        if(!*dir_string)
+        {
+            result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+            goto exit;
+        }
+        
+        globus_libc_snprintf(*dir_string,
+                             dir_string_length, "%s", full_filename);
+        
+        filename_string_length = strlen(full_filename) - dir_string_length + 1;
+        
+        *filename_string = malloc(filename_string_length);
+        
+        if(!*filename_string)
+        {
+            result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+            if(*dir_string)
+            {
+                free(*dir_string);
+            }
+            goto exit;
+        }
+        
+        globus_libc_snprintf(*filename_string,
+                             filename_string_length, "%s",
+                             &full_filename[dir_string_length]);
+    }
+
+ exit:
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+
+/**
+ * @name UNIX - Get Current Working Directory
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the current working directory on the system.  
+ *
+ * @param working_dir
+ *        The current working directory
+ * @return
+ *        GLOBUS_SUCCESS or an error object identifier
+ */
+globus_result_t
+globus_gsi_sysconfig_get_current_working_dir_unix(
+    char **                             working_dir)
+{
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    char *                              buffer = NULL;
+    char *                              result_buffer = NULL;
+    int                                 length = 128;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_current_working_dir_unix";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    buffer = malloc(length);
+    if(!buffer)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+
+    while(1)
+    {
+        result_buffer = getcwd(buffer, length);
+        if(!result_buffer && errno == ERANGE)
+        {
+            length *= 2;
+            if(!(result_buffer = realloc(buffer, length)))
+            {
+                free(buffer);
+                result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+                goto exit;
+            }
+
+            buffer = result_buffer;
+        }
+        else if(!result_buffer)
+        {
+            result = 
+                globus_error_put(globus_error_wrap_errno_error(
+                    GLOBUS_GSI_SYSCONFIG_MODULE,
+                    errno,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_ERRNO,
+                    "%s:%d: Couldn't get the current working directory",
+                    __FILE__, __LINE__));
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    *working_dir = result_buffer;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Get HOME Directory
+ * @ingroup globus_i_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the HOME Directory of the current user.  Should
+ * be the $HOME environment variable.
+ *
+ * @param home_dir
+ *        The home directory of the current user
+ * @return
+ *        GLOBUS_SUCCESS if no error occured, otherwise
+ *        an error object is returned.
+ */
+globus_result_t
+globus_gsi_sysconfig_get_home_dir_unix(
+    char **                             home_dir,
+    globus_gsi_statcheck_t *            status)
+{
+    char *                              temp_home_dir;
+    struct passwd                       pwd;
+    struct passwd *                     pwd_result;
+    char *                              buf;
+    int                                 buf_len;
+    globus_result_t                     result;
+    static char *                        _function_name_ =
+        "globus_i_gsi_sysconfig_get_home_dir_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *home_dir = NULL;
+
+    /* the below seems to be fairly portable */
+    
+    buf_len = sysconf(_SC_GETPW_R_SIZE_MAX) + 1;
+
+    buf = malloc(buf_len);
+
+    if(buf == NULL)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+    
+    if(globus_libc_getpwuid_r(geteuid(),
+                              &pwd,
+                              buf,
+                              buf_len,
+                              &pwd_result) != 0)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PW_ENTRY,
+            ("Error occured for uid: %d",geteuid()));        
+        goto exit;
+    }
+
+    if(pwd_result == NULL || pwd_result->pw_dir == NULL)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PW_ENTRY,
+            ("Error occured for uid: %d",geteuid()));        
+        goto exit;        
+    }
+
+    temp_home_dir = malloc(strlen(pwd_result->pw_dir) + 1);
+    strncpy(temp_home_dir, pwd_result->pw_dir, 
+            strlen(pwd_result->pw_dir) + 1);
+
+    if(temp_home_dir)
+    {
+        result = GLOBUS_GSI_SYSCONFIG_FILE_EXISTS(temp_home_dir, status);
+        if(result != GLOBUS_SUCCESS)
+        {
+            globus_object_t *               error_obj;
+            free(temp_home_dir);
+            error_obj = globus_error_get(result);
+            globus_object_free(error_obj);
+            result = GLOBUS_SUCCESS;
+            *status = GLOBUS_FILE_INVALID;
+            goto exit;
+        }
+
+        *home_dir = temp_home_dir;
+    }
+    else
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_HOME_DIR,
+            ("Could not get a defined HOME directory for user id: %d\n",
+             geteuid()));
+        goto exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+
+ exit:
+
+    if(buf != NULL)
+    {
+        free(buf);
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - File Exists
+ * @ingroup globus_i_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Check if the file exists
+ *
+ * @param filename the filename of the file to check for
+ * @param status  the resulting status of the file
+ *
+ * @return
+ *        GLOBUS_SUCCESS for almost all cases (even if the file
+ *        doesn't exist), otherwise an error object identifier
+ *        wrapping the system errno is returned
+ */
+globus_result_t
+globus_gsi_sysconfig_file_exists_unix(
+    const char *                        filename,
+    globus_gsi_statcheck_t *            status)
+{
+    struct stat                         stx;
+    globus_result_t                     result;
+
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_file_exists_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    if (stat(filename,&stx) == -1)
+    {
+        switch(errno)
+        {
+          case ENOENT:
+          case ENOTDIR:
+            *status = GLOBUS_FILE_DOES_NOT_EXIST;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+            
+          case EACCES:
+            
+            *status = GLOBUS_FILE_BAD_PERMISSIONS;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          default:
+            result = globus_error_put(
+                globus_error_wrap_errno_error(
+                    GLOBUS_GSI_SYSCONFIG_MODULE,
+                    errno,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_CHECKING_FILE_EXISTS,
+                    __FILE__":%d:%s: Error getting status "
+                    "of certificate directory: %s\n",
+                    __LINE__, 
+                    _function_name_,
+                    filename));
+            goto exit;
+        
+        }
+    }
+
+    /*
+     * use any stat output as random data, as it will 
+     * have file sizes, and last use times in it. 
+     */
+    RAND_add((void*)&stx,sizeof(stx),2);
+
+    if (stx.st_size == 0)
+    {
+        *status = GLOBUS_FILE_ZERO_LENGTH;
+        result = GLOBUS_SUCCESS;
+        goto exit;
+    }
+
+    if(stx.st_mode & S_IFDIR)
+    {
+        *status = GLOBUS_FILE_DIR;
+    }
+    else if(stx.st_mode & (S_IFREG | S_IFLNK))
+    {
+        *status = GLOBUS_FILE_VALID;
+    }
+    else
+    {
+        *status = GLOBUS_FILE_INVALID;
+    }
+
+    result = GLOBUS_SUCCESS;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}    
+/* @} */
+
+
+/**
+ * UNIX - Check File Status for Key
+ * @ingroup globus_i_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * This is a convenience function used to check the status of a 
+ * private key file.  The desired status is only the current user has
+ * ownership and read permissions, everyone else should not be able
+ * to access it.
+ * 
+ * @param filename
+ *        The name of the file to check the status of
+ * @param status
+ *        The status of the file being checked
+ *        see @ref globus_gsi_statcheck_t for possible values
+ *        of this variable 
+ *
+ * @return 
+ *        GLOBUS_SUCCESS if the status of the file was able
+ *        to be determined.  Otherwise, an error object
+ *        identifier
+ *
+ * @see globus_gsi_statcheck_t
+ */
+globus_result_t
+globus_gsi_sysconfig_check_keyfile_unix(
+    const char *                        filename,
+    globus_gsi_statcheck_t *            status)
+{
+    struct stat                         stx;
+    globus_result_t                     result;
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_check_keyfile_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    if (stat(filename,&stx) == -1)
+    {
+        switch (errno)
+        {
+          case ENOENT:
+          case ENOTDIR:
+            *status = GLOBUS_FILE_DOES_NOT_EXIST;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          case EACCES:
+
+            *status = GLOBUS_FILE_BAD_PERMISSIONS;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          default:
+            result = globus_error_put(
+                globus_error_wrap_errno_error(
+                    GLOBUS_GSI_SYSCONFIG_MODULE,
+                    errno,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    __FILE__":%d:%s: Error getting status of keyfile: %s\n",
+                    __LINE__,
+                    _function_name_,
+                    filename));
+            goto exit;
+        }
+    }
+
+    /*
+     * use any stat output as random data, as it will 
+     * have file sizes, and last use times in it. 
+     */
+    RAND_add((void*)&stx,sizeof(stx),2);
+
+    if (stx.st_uid != getuid())
+    {
+        *status = GLOBUS_FILE_NOT_OWNED;
+        result = GLOBUS_SUCCESS;
+        goto exit;
+    }
+
+    /* check that the key file is not x by user, or rwx by group or others */
+    if (stx.st_mode & (S_IXUSR | 
+                       S_IRGRP | S_IWGRP | S_IXGRP |
+                       S_IROTH | S_IWOTH | S_IXOTH))
+    {
+        GLOBUS_I_GSI_SYSCONFIG_DEBUG_FPRINTF(
+            2, (stderr, "checkstat:%s:mode:%o\n", filename, stx.st_mode)); 
+
+        *status = GLOBUS_FILE_BAD_PERMISSIONS;
+        result = GLOBUS_SUCCESS;
+        goto exit;
+    }
+
+    if (stx.st_size == 0)
+    {
+        *status = GLOBUS_FILE_ZERO_LENGTH;
+        result = GLOBUS_SUCCESS;
+        goto exit;
+    }
+
+    if(stx.st_mode & S_IFDIR)
+    {
+        *status = GLOBUS_FILE_DIR;
+    }
+    else if(stx.st_mode & (S_IFLNK | S_IFREG))
+    {
+        *status = GLOBUS_FILE_VALID;
+    }
+    else
+    {
+        *status = GLOBUS_FILE_INVALID;
+    }
+
+    result = GLOBUS_SUCCESS;
+
+ exit:
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Check File Status for Cert
+ * @ingroup globus_i_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * This is a convenience function used to check the status of a 
+ * certificate file.  The desired status is the current user has
+ * ownership and read/write permissions, while group and others only
+ * have read permissions.
+ * 
+ * @param filename
+ *        The name of the file to check the status of
+ * @param status
+ *        The status of the file being checked
+ *        see @ref globus_gsi_statcheck_t for possible values
+ *        of this variable 
+ *
+ * @return 
+ *        GLOBUS_SUCCESS if the status of the file was able
+ *        to be determined.  Otherwise, an error object
+ *        identifier
+ *
+ * @see globus_gsi_statcheck_t
+ */
+globus_result_t
+globus_gsi_sysconfig_check_certfile_unix(
+    const char *                        filename,
+    globus_gsi_statcheck_t *            status)
+{
+    struct stat                         stx;
+    globus_result_t                     result;
+    static char *                       _function_name_ =
+        "globus_i_gsi_sysconfig_check_certfile_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+    
+    if (stat(filename,&stx) == -1)
+    {
+        switch (errno)
+        {
+          case ENOENT:
+          case ENOTDIR:
+            *status = GLOBUS_FILE_DOES_NOT_EXIST;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          case EACCES:
+
+            *status = GLOBUS_FILE_BAD_PERMISSIONS;
+            result = GLOBUS_SUCCESS;
+            goto exit;
+
+          default:
+            result = globus_error_put(
+                globus_error_wrap_errno_error(
+                    GLOBUS_GSI_SYSCONFIG_MODULE,
+                    errno,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_FILENAME,
+                    __FILE__":%d:%s: Error getting status of cert file %s\n",
+                    __LINE__,
+                    _function_name_,
+                    filename));
+            goto exit;
+        }
+    }
+
+    /*
+     * use any stat output as random data, as it will 
+     * have file sizes, and last use times in it. 
+     */
+    RAND_add((void*)&stx,sizeof(stx),2);
+
+    if (stx.st_uid != getuid())
+    {
+        *status = GLOBUS_FILE_NOT_OWNED;
+        result = GLOBUS_SUCCESS;
+        goto exit;
+    }
+
+    /* check that the cert file is not x by user, or wx by group or others */
+    if (stx.st_mode & (S_IXUSR |
+                       S_IWGRP | S_IXGRP |
+                       S_IWOTH | S_IXOTH))
+    {
+        GLOBUS_I_GSI_SYSCONFIG_DEBUG_FPRINTF(
+            2, (stderr, "checkstat:%s:mode:%o\n",filename,stx.st_mode));
+
+        *status = GLOBUS_FILE_BAD_PERMISSIONS;
+        result = GLOBUS_SUCCESS;
+        goto exit;
+    }
+    
+    if (stx.st_size == 0)
+    {
+        *status = GLOBUS_FILE_ZERO_LENGTH;
+        result = GLOBUS_SUCCESS;
+        goto exit;
+    }
+
+    if(stx.st_mode & S_IFDIR)
+    {
+        *status = GLOBUS_FILE_DIR;
+    }
+    else if(stx.st_mode & (S_IFREG | S_IFLNK))
+    {
+        *status = GLOBUS_FILE_VALID;
+    }
+    else
+    {
+        *status = GLOBUS_FILE_INVALID;
+    }
+
+    *status = GLOBUS_FILE_VALID;
+    result = GLOBUS_SUCCESS;
+
+ exit:
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Get Trusted CA Cert Dir
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the Trusted Certificate Directory containing the trusted
+ * Certificate Authority certificates.  This directory is determined
+ * in the order shown below.  Failure in one method results in attempting
+ * the next.
+ *
+ * <ol>
+ * <li> <b>X509_CERT_DIR environment variable</b> - if this is set, the
+ * trusted certificates will be searched for in that directory.  This
+ * variable allows the end user to specify the location of trusted
+ * certificates.
+ * <li> <b>$HOME/.globus/certificates</b> - If this
+ * directory exists, and the previous methods of determining the trusted
+ * certs directory failed, this directory will be used.  
+ * <li> <b>/etc/grid-security/certificates</b> - This location is intended
+ * to be independant of the globus installation ($GLOBUS_LOCATION), and 
+ * is generally only writeable by the host system administrator.  
+ * <li> <b>$GLOBUS_LOCATION/share/certificates</b>
+ * </ol>
+ *
+ * @param cert_dir
+ *        The trusted certificates directory
+ * @return
+ *        GLOBUS_SUCCESS if no error occurred, and a sufficient trusted
+ *        certificates directory was found.  Otherwise, an error object 
+ *        identifier returned.
+ */
+globus_result_t
+globus_gsi_sysconfig_get_cert_dir_unix(
+    char **                             cert_dir)
+{
+    char *                              env_cert_dir = NULL;
+    char *                              local_cert_dir = NULL;
+    char *                              default_cert_dir = NULL;
+    char *                              installed_cert_dir = NULL;
+    globus_result_t                     result;
+    char *                              home = NULL;
+    char *                              globus_location;
+    globus_gsi_statcheck_t              status;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_cert_dir_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+    
+    *cert_dir = NULL;
+
+    if(getenv(X509_CERT_DIR))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_dir_string(
+            cert_dir, 
+            & env_cert_dir,
+            & status,
+            getenv(X509_CERT_DIR));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR);
+            goto error_exit;
+        }
+
+        if(status != GLOBUS_FILE_DIR)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR,
+                ("X509_CERT_DIR=%s, but the the path "
+                 "is not a valid directory", env_cert_dir));
+            goto error_exit;
+        }
+    }
+
+    /* now check for a trusted CA directory in the user's home directory */
+    if(!(*cert_dir))
+    {
+        result = GLOBUS_GSI_SYSCONFIG_GET_HOME_DIR(&home, &status);
+        if(result != GLOBUS_SUCCESS)
+        {
+	    home = NULL;
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR);
+            goto error_exit;
+        }
+        
+        if(home && status == GLOBUS_FILE_DIR)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_dir_string(
+                cert_dir, 
+                & local_cert_dir,
+                & status,
+                "%s%s%s",
+                home,
+                FILE_SEPERATOR,
+                X509_LOCAL_TRUSTED_CERT_DIR);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR);
+                goto error_exit;
+            }
+        }
+    }
+
+    /* now look in /etc/grid-security/certificates */
+    if (!(*cert_dir))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_dir_string(
+            cert_dir,
+            &installed_cert_dir,
+            &status,
+            X509_DEFAULT_TRUSTED_CERT_DIR);
+        if(result != GLOBUS_SUCCESS)
+        {
+            if(status != GLOBUS_FILE_BAD_PERMISSIONS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR);
+                goto error_exit;
+            }
+            else
+            {
+                globus_object_t *       error_obj;
+                error_obj = globus_error_get(result);
+                globus_object_free(error_obj);
+            }
+        }
+    }
+
+    /* now look in  $GLOBUS_LOCATION/share/certificates */
+    if (!(*cert_dir))
+    {
+        globus_location = getenv("GLOBUS_LOCATION");
+        
+        if (globus_location)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_dir_string(
+                cert_dir,
+                &default_cert_dir,
+                &status,
+                "%s%s%s",
+                globus_location,
+                FILE_SEPERATOR,
+                X509_INSTALLED_TRUSTED_CERT_DIR);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR);
+                goto error_exit;
+            }
+        }
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_FPRINTF(
+        2, (stderr, "Using cert_dir = %s\n", 
+            (*cert_dir ? *cert_dir : "null")));
+
+    if(!(*cert_dir))
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_DIR,
+            ("The trusted certificates directory could not be "
+             "found in any of the following locations: \n"
+             "1) env. var. X509_CERT_DIR=%s\n"
+             "2) %s\n3) %s\n4) %s\n",
+             env_cert_dir ? env_cert_dir : "NULL",
+             local_cert_dir ? local_cert_dir : "NULL",
+             installed_cert_dir ? installed_cert_dir : "NULL",
+             default_cert_dir ? default_cert_dir : "NULL"));
+
+        goto error_exit;
+    }
+
+    result = GLOBUS_SUCCESS;
+    goto done;
+
+ error_exit:
+    
+    if(*cert_dir)
+    {
+        globus_libc_free(*cert_dir);
+        *cert_dir = NULL;
+    }
+
+ done:
+
+    if(home != NULL)
+    {
+	free(home);
+    }
+    
+    if(env_cert_dir && (env_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(env_cert_dir);
+    }
+    if(local_cert_dir && (local_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(local_cert_dir);
+    }
+    if(installed_cert_dir && (installed_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(installed_cert_dir);
+    }
+    if(default_cert_dir && (default_cert_dir != (*cert_dir)))
+    {
+        globus_libc_free(default_cert_dir);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Get User Certificate Filename
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the User Certificate Filename based on the current user's
+ * environment.  The following locations are searched for cert and key
+ * files in order:
+ * 
+ * <ol>
+ * <li>environment variables X509_USER_CERT and X509_USER_KEY
+ * <li>$HOME/.globus/usercert.pem and 
+ *     $HOME/.globus/userkey.pem
+ * <li>$HOME/.globus/usercred.p12 - this is a PKCS12 credential
+ * </ol>
+ *
+ * @param user_cert
+ *        pointer the filename of the user certificate
+ * @param user_key
+ *        pointer to the filename of the user key
+ * @return
+ *        GLOBUS_SUCCESS if the cert and key files were found in one
+ *        of the possible locations, otherwise an error object identifier
+ *        is returned
+ */
+globus_result_t
+globus_gsi_sysconfig_get_user_cert_filename_unix(
+    char **                             user_cert,
+    char **                             user_key)
+{
+    char *                              home = NULL;
+    char *                              env_user_cert = NULL;
+    char *                              env_user_key = NULL;
+    char *                              default_user_cert = NULL;
+    char *                              default_user_key = NULL;
+    char *                              default_pkcs12_user_cred = NULL;
+    globus_gsi_statcheck_t              status;
+    globus_result_t                     result;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_user_cert_filename_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *user_cert = NULL;
+    *user_key = NULL;
+
+    /* first, check environment variables for valid filenames */
+
+    if(getenv(X509_USER_CERT))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            user_cert,
+            & env_user_cert,
+            & status,
+            getenv(X509_USER_CERT));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto done;
+        }
+
+        if(status != GLOBUS_FILE_VALID)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+                (X509_USER_CERT"=%s %s",
+                 env_user_cert,
+                 globus_l_gsi_sysconfig_status_strings[status]));
+            goto done;
+        }
+                 
+    }
+
+    if(getenv(X509_USER_KEY))
+    {
+        result = globus_i_gsi_sysconfig_create_key_string(
+            user_key,
+            & env_user_key,
+            & status,
+            getenv(X509_USER_KEY));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+            goto done;
+        }
+
+        if(status != GLOBUS_FILE_VALID)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+                (X509_USER_KEY"=%s %s",
+                 env_user_key,
+                 globus_l_gsi_sysconfig_status_strings[status]));
+            goto done;
+        }
+    }
+
+    /* next, check default locations */
+    if(!(*user_cert) || !(*user_key))
+    {
+        result = GLOBUS_GSI_SYSCONFIG_GET_HOME_DIR(&home, &status);
+        if(result != GLOBUS_SUCCESS)
+        {
+            home = NULL;
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto done;
+        }
+
+        if(home && status == GLOBUS_FILE_DIR)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_string(
+                user_cert,
+                & default_user_cert,
+                & status,
+                "%s%s%s",
+                home,
+                FILE_SEPERATOR,
+                X509_DEFAULT_USER_CERT);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+                goto done;
+            }
+        
+            result = globus_i_gsi_sysconfig_create_key_string(
+                user_key,
+                & default_user_key,
+                & status,
+                "%s%s%s",
+                home,
+                FILE_SEPERATOR,
+                X509_DEFAULT_USER_KEY);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+                goto done;
+            }
+
+            if((*user_cert) && !(*user_key))
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("User certificate is at: %s, but a user key "
+                     "could not be found at: %s",
+                     *user_cert, default_user_key));
+                *user_cert = NULL;
+                goto done;
+            }
+            
+            if((*user_key) && !(*user_cert))
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("User key is at: %s, but a user certificate "
+                     "could not be found at: %s",
+                     *user_key, default_user_cert));
+                *user_key = NULL;
+                goto done;
+            }
+        }
+    }
+
+    /* if the cert & key don't exist in the default locations
+     * or those specified by the environment variables, a
+     * pkcs12 cert will be searched for
+     */
+    if(!(*user_cert) && !(*user_key))
+    {
+        if(home)
+        {
+            free(home);
+            home = NULL;
+        }
+
+        result = GLOBUS_GSI_SYSCONFIG_GET_HOME_DIR(&home, &status);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+            goto done;
+        }
+
+        if(home && status == GLOBUS_FILE_DIR)
+        {
+            result = globus_i_gsi_sysconfig_create_key_string(
+                user_key,
+                & default_pkcs12_user_cred,
+                & status,
+                "%s%s%s",
+                home,
+                FILE_SEPERATOR,
+                X509_DEFAULT_PKCS12_FILE);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+                goto done;
+            }
+            *user_cert = *user_key;
+        }
+    }
+
+    if(!(*user_cert))
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+            ("The user cert could not be found in: \n"
+             "1) env. var. X509_USER_CERT=%s\n"
+             "2) %s\n3) %s\n\n",
+             env_user_cert ? env_user_cert : "NULL",
+             default_user_cert ? default_user_cert : "NULL",
+             default_pkcs12_user_cred ? default_pkcs12_user_cred : "NULL"));
+        goto done;
+    }
+
+    if(!(*user_key))
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+            ("The user key could not be found in:\n,"
+             "1) env. var. X509_USER_KEY=%s\n"
+             "2) %s\n3) %s\n\n",
+             env_user_key ? env_user_key : "NULL",
+             default_user_key ? default_user_key : "NULL",
+             default_pkcs12_user_cred ? default_pkcs12_user_cred : "NULL"));
+        goto done;
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_FPRINTF(
+        2, (stderr,"Using x509_user_cert=%s\n      x509_user_key =%s\n",
+            *user_cert, *user_key));
+
+    result = GLOBUS_SUCCESS;
+
+ done:
+
+    if(env_user_cert && env_user_cert != (*user_cert))
+    {
+        globus_libc_free(env_user_cert);
+    }
+    if(env_user_key && env_user_key != (*user_key))
+    {
+        globus_libc_free(env_user_key);
+    }
+    if(default_user_cert && default_user_cert != (*user_cert))
+    {
+        globus_libc_free(default_user_cert);
+    }
+    if(default_user_key && default_user_key != (*user_key))
+    {
+        globus_libc_free(default_user_key);
+    }
+    if(home)
+    {
+        free(home);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Get Host Certificate and Key Filenames
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the Host Certificate and Key Filenames based on the current user's
+ * environment.  The host cert and key are searched for in the following 
+ * locations (in order):
+ *
+ * <ol>
+ * <li>X509_USER_CERT and X509_USER_KEY environment variables
+ * <li>registry keys x509_user_cert and x509_user_key in software\Globus\GSI
+ * <li>SLANG: NOT DETERMINED - this is the default location
+ * <li><GLOBUS_LOCATION>\etc\host[cert|key].pem
+ * <li><users home directory>\.globus\host[cert|key].pem
+ * </ol>
+ * 
+ * @param host_cert
+ *        pointer to the host certificate filename
+ * @param host_key
+ *        pointer to the host key filename
+ *
+ * @return
+ *        GLOBUS_SUCCESS if the host cert and key were found, otherwise
+ *        an error object identifier is returned 
+ */
+globus_result_t
+globus_gsi_sysconfig_get_host_cert_filename_unix(
+    char **                             host_cert,
+    char **                             host_key)
+{
+    char *                              home = NULL;
+    char *                              env_host_cert = NULL;
+    char *                              env_host_key = NULL;
+    char *                              default_host_cert = NULL;
+    char *                              default_host_key = NULL;
+    char *                              installed_host_cert = NULL;
+    char *                              installed_host_key = NULL;
+    char *                              local_host_cert = NULL;
+    char *                              local_host_key = NULL;
+    char *                              globus_location = NULL;
+    globus_gsi_statcheck_t              status;
+    globus_result_t                     result;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_host_cert_filename_unix";
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+    
+    *host_cert = NULL;
+    *host_key = NULL;
+    
+    /* first check environment variables for valid filenames */
+    
+    if(getenv(X509_USER_CERT))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            host_cert,
+            & env_host_cert,
+            & status,
+            getenv(X509_USER_CERT));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto done;
+        }
+        if(status != GLOBUS_FILE_VALID)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+                (X509_USER_CERT"=%s %s",
+                 env_host_cert,
+                 globus_l_gsi_sysconfig_status_strings[status]));
+            goto done;
+        }
+    }
+    
+    if(getenv(X509_USER_KEY))
+    {
+        result = globus_i_gsi_sysconfig_create_key_string(
+            host_key,
+            & env_host_key,
+            & status,
+            getenv(X509_USER_KEY));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+            goto done;
+        }
+        if(status != GLOBUS_FILE_VALID)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+                (X509_USER_CERT"=%s %s",
+                 env_host_key,
+                 globus_l_gsi_sysconfig_status_strings[status]));
+            goto done;
+        }
+    }
+
+/* G.Ganis 16/4/2003 begin */
+    /* now check validity of files found (if any) */
+    if (*host_cert )
+    {
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            host_cert,
+            & default_host_cert,
+            & status,
+            "%s%s%s%s",
+            X509_DEFAULT_CERT_DIR,
+            FILE_SEPERATOR,
+            X509_HOST_PREFIX,
+            X509_CERT_SUFFIX);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto done;
+        }
+    }
+    if (*host_key )
+    {
+        result = globus_i_gsi_sysconfig_create_key_string(
+            host_key,
+            & default_host_key,
+            & status,
+            "%s%s%s%s",
+            X509_DEFAULT_CERT_DIR,
+            FILE_SEPERATOR,
+            X509_HOST_PREFIX,
+            X509_KEY_SUFFIX);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+            goto done;
+        }
+    }        
+/* G.Ganis 16/4/2003 end */
+
+        
+    /* now check default locations for valid filenames */
+    if(!(*host_cert) || !(*host_key))
+    {
+
+      /* G.Ganis 16/4/2003 begin */
+      /*
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            host_cert,
+            & default_host_cert,
+            & status,
+            "%s%s%s%s",
+            X509_DEFAULT_CERT_DIR,
+            FILE_SEPERATOR,
+            X509_HOST_PREFIX,
+            X509_CERT_SUFFIX);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto done;
+        }
+        
+        result = globus_i_gsi_sysconfig_create_key_string(
+            host_key,
+            & default_host_key,
+            & status,
+            "%s%s%s%s",
+            X509_DEFAULT_CERT_DIR,
+            FILE_SEPERATOR,
+            X509_HOST_PREFIX,
+            X509_KEY_SUFFIX);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+            goto done;
+        }
+      */
+      /* G.Ganis 16/4/2003 end */
+        
+        if((*host_cert) && !(*host_key))
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                ("Host certificate is at: %s, but a host cert "
+                 "coult not be found at: %s",
+                 *host_cert, default_host_key));
+            free(*host_cert);
+            goto done;
+        }
+        
+        if((*host_key) && !(*host_cert))
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                ("Host key is at: %s, but a host certificate "
+                 "could not be found at: %s",
+                 *host_key, default_host_cert));
+            free(*host_key);
+            goto done;
+        }
+    }
+
+    /* now check installed location for host cert */
+    if(!(*host_cert) || !(*host_key))
+    {
+        globus_location = getenv("GLOBUS_LOCATION");
+
+        if(globus_location)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_string(
+                host_cert,
+                & installed_host_cert,
+                & status,
+                "%s%s%s%s%s%s",
+                globus_location,
+                FILE_SEPERATOR,
+                X509_INSTALLED_CERT_DIR,
+                FILE_SEPERATOR,
+                X509_HOST_PREFIX,
+                X509_CERT_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+                goto done;
+            }
+
+            result = globus_i_gsi_sysconfig_create_key_string(
+                host_key,
+                & installed_host_key,
+                & status,
+                "%s%s%s%s%s%s",
+                globus_location,
+                FILE_SEPERATOR,
+                X509_INSTALLED_CERT_DIR,
+                FILE_SEPERATOR,
+                X509_HOST_PREFIX,
+                X509_KEY_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+                goto done;
+            }
+
+            if((*host_cert) && !(*host_key))
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("Host certificate is at: %s, but a host cert "
+                     "coult not be found at: %s",
+                     *host_cert, installed_host_key));
+                free(*host_cert);
+                goto done;
+            }
+
+            if((*host_key) && !(*host_cert))
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("Host key is at: %s, but a host certificate "
+                     "could not be found at: %s",
+                     *host_key, installed_host_cert));
+                free(*host_key);
+                goto done;
+            }
+        }
+    }
+    
+    if(!(*host_cert) || !(*host_key))
+    {
+        result = GLOBUS_GSI_SYSCONFIG_GET_HOME_DIR(&home, &status);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            home = NULL;
+            goto done;
+        }
+
+        if(home && status == GLOBUS_FILE_DIR)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_string(
+                host_cert,
+                & local_host_cert,
+                & status,
+                "%s%s%s%s%s%s",
+                home,
+                FILE_SEPERATOR,
+                X509_LOCAL_CERT_DIR,
+                FILE_SEPERATOR,
+                X509_HOST_PREFIX,
+                X509_CERT_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+                goto done;
+            }
+            
+            result = globus_i_gsi_sysconfig_create_key_string(
+                host_key,
+                & local_host_key,
+                & status,
+                "%s%s%s%s%s%s",
+                home,
+                FILE_SEPERATOR,
+                X509_LOCAL_CERT_DIR,
+                FILE_SEPERATOR,
+                X509_HOST_PREFIX,
+                X509_KEY_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+                goto done;
+            }
+
+            if((*host_cert) && !(*host_key))
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("Host certificate is at: %s, but a host cert "
+                     "coult not be found at: %s",
+                     *host_cert, local_host_key));
+                *host_cert = NULL;
+                goto done;
+            }
+
+            if((*host_key) && !(*host_cert))
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("Host key is at: %s, but a host certificate "
+                     "could not be found at: %s",
+                     *host_key, local_host_cert));
+                *host_key = NULL;
+                goto done;
+            }
+        }
+    }
+    
+    if(!(*host_cert) || !(*host_key))
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_FILENAME,
+            ("The host cert could not be found in: \n"
+             "1) env. var. X509_USER_CERT=%s\n"
+             "2) %s\n3) %s\n4) %s\n\n"
+             "The host key could not be found in:\n"
+             "1) env. var. X509_USER_KEY=%s\n"
+             "2) %s\n3) %s\n4) %s\n",
+             env_host_cert ? env_host_cert : "NULL",
+             default_host_cert ? default_host_cert : "NULL",
+             installed_host_cert ? installed_host_cert : "NULL",
+             local_host_cert ? local_host_cert : "NULL",
+             env_host_key ? env_host_key : "NULL",
+             default_host_key ? default_host_key : "NULL",
+             installed_host_key ? installed_host_key : "NULL",
+             local_host_key ? local_host_key : "NULL"));
+        
+        goto done;
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_FPRINTF(
+        2, (stderr, "Using x509_user_cert=%s\n      x509_user_key =%s\n",
+            *host_cert , *host_key));
+    
+    result = GLOBUS_SUCCESS;
+    
+ done:
+    
+    if(env_host_cert && env_host_cert != *host_cert)
+    {
+        globus_libc_free(env_host_cert);
+    }
+    if(env_host_key && env_host_key != *host_key)
+    {
+        globus_libc_free(env_host_key);
+    }
+    if(installed_host_cert && installed_host_cert != *host_cert)
+    {
+        globus_libc_free(installed_host_cert);
+    }
+    if(installed_host_key && installed_host_key != *host_key)
+    {
+        globus_libc_free(installed_host_key);
+    }
+    if(local_host_cert && local_host_cert != *host_cert)
+    {
+        globus_libc_free(local_host_cert);
+    }
+    if(local_host_key && local_host_key != *host_key)
+    {
+        globus_libc_free(local_host_key);
+    }
+    if(default_host_cert && default_host_cert != *host_cert)
+    {
+        globus_libc_free(default_host_cert);
+    }
+    if(default_host_key && default_host_key != *host_key)
+    {
+        globus_libc_free(default_host_key);
+    }
+
+    if(home)
+    {
+        free(home);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Get Service Certificate and Key Filenames
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the Service Certificate Filename based on the current user's
+ * environment.  The host cert and key are searched for in the following 
+ * locations (in order):
+ *
+ * <ol>
+ * <li>X509_USER_CERT and X509_USER_KEY environment variables
+ * <li>/etc/grid-security/{service_name}/{service_name}[cert|key].pem
+ * <li>GLOBUS_LOCATION\etc\{service_name}\{service_name}[cert|key].pem
+ *     So for example, if my service was named: myservice, the location
+ *     of the certificate would be: 
+ *     GLOBUS_LOCATION\etc\myservice\myservicecert.pem
+ * <li><users home>\.globus\{service_name}\{service_name}[cert|key].pem
+ * </ol>
+ * 
+ * @param service_name
+ *        The name of the service which allows us to determine the
+ *        locations of cert and key files to look for
+ * @param service_cert
+ *        pointer to the host certificate filename
+ * @param service_key
+ *        pointer to the host key filename
+ *
+ * @return
+ *        GLOBUS_SUCCESS if the service cert and key were found, otherwise
+ *        an error object identifier 
+ */
+globus_result_t
+globus_gsi_sysconfig_get_service_cert_filename_unix(
+    char *                              service_name,
+    char **                             service_cert,
+    char **                             service_key)
+{
+    char *                              home = NULL;
+    char *                              env_service_cert = NULL;
+    char *                              env_service_key = NULL;
+    char *                              default_service_cert = NULL;
+    char *                              default_service_key = NULL;
+    char *                              installed_service_cert = NULL;
+    char *                              installed_service_key = NULL;
+    char *                              local_service_cert = NULL;
+    char *                              local_service_key = NULL;
+    char *                              globus_location = NULL;
+    globus_gsi_statcheck_t              status;
+    globus_result_t                     result;
+
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_service_cert_filename_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *service_cert = NULL;
+    *service_key = NULL;
+
+    /* first check environment variables for valid filenames */
+
+    if(getenv(X509_USER_CERT))
+    {
+        result = globus_i_gsi_sysconfig_create_cert_string(
+            service_cert,
+            & env_service_cert,
+            & status,
+            getenv(X509_USER_CERT));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            goto done;
+        }
+
+        if(status != GLOBUS_FILE_VALID || !(*service_cert))
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+                (X509_USER_CERT"=%s %s",
+                 getenv(X509_USER_CERT),
+                 globus_l_gsi_sysconfig_status_strings[status]));
+            goto done;
+        }
+    }
+
+    if(getenv(X509_USER_KEY))
+    {
+        result = globus_i_gsi_sysconfig_create_key_string(
+            service_key,
+            & env_service_key,
+            & status,
+            getenv(X509_USER_KEY));
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+            goto done;
+        }
+
+        if(status != GLOBUS_FILE_VALID || !*service_key)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                ("X509_USER_KEY=%s is not a valid service key file",
+                 env_service_key));
+            goto done;
+        }
+    }
+
+    /* now check default locations for valid filenames */
+    if(!(*service_cert) || !(*service_key))
+    {
+        result = GLOBUS_GSI_SYSCONFIG_GET_HOME_DIR(&home, &status);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            home = NULL;
+            goto done;
+        }
+
+        if(home && status == GLOBUS_FILE_DIR)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_string(
+                service_cert,
+                & default_service_cert,
+                & status,
+                "%s%s%s%s%s%s",
+                X509_DEFAULT_CERT_DIR,
+                FILE_SEPERATOR,
+                service_name,
+                FILE_SEPERATOR,
+                service_name,
+                X509_CERT_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+                goto done;
+            }
+
+            result = globus_i_gsi_sysconfig_create_key_string(
+                service_key,
+                & default_service_key,
+                & status,
+                "%s%s%s%s%s%s",
+                X509_DEFAULT_CERT_DIR,
+                FILE_SEPERATOR,
+                service_name,
+                FILE_SEPERATOR,
+                service_name,
+                X509_KEY_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+                goto done;
+            }
+            
+            if(*service_cert && !*service_key)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("The service certificate was found at: %s, ",
+                     "but no service key could be found at: %s",
+                     *service_cert, default_service_key));
+                goto done;
+            }
+            
+            if(!*service_cert && *service_key)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING,
+                    ("The service key was found at: %s, "
+                     "but no service cert could be found at: %s",
+                     *service_key, default_service_cert));
+                goto done;
+            }
+        }
+    }
+
+    /* now check intstalled location for service cert */
+    if(!(*service_cert) || !(*service_key))
+    {
+        globus_location = getenv("GLOBUS_LOCATION");
+
+        if(globus_location)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_string(
+                service_cert,
+                & installed_service_cert,
+                & status,
+                "%s%s%s%s%s%s%s%s",
+                globus_location,
+                FILE_SEPERATOR,
+                X509_INSTALLED_CERT_DIR,
+                FILE_SEPERATOR,
+                service_name,
+                FILE_SEPERATOR,
+                service_name,
+                X509_CERT_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+                goto done;
+            }
+               
+            result = globus_i_gsi_sysconfig_create_key_string(
+                service_key,
+                & installed_service_key,
+                & status,
+                "%s%s%s%s%s%s%s%s",
+                globus_location,
+                FILE_SEPERATOR,
+                X509_INSTALLED_CERT_DIR,
+                FILE_SEPERATOR,
+                service_name,
+                FILE_SEPERATOR,
+                service_name,
+                X509_KEY_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING);
+                goto done;
+            }
+
+            if(*service_cert && !*service_key)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("Service certificate was found at: %s, but no "
+                     "service key was found at: %s",
+                     *service_cert, installed_service_key));
+                goto done;
+            }
+
+            if(!*service_cert && *service_key)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("Service key was found at: %s, but no "
+                     "service certificate was found at: %s",
+                     *service_key, installed_service_cert));
+                goto done;
+            }
+        }
+    }
+    
+    if(!(*service_cert) || !(*service_key))
+    {
+        /* need to change this if I ever fix the status mess */
+        if(home)
+        {
+            free(home);
+            home = NULL;
+        }
+
+        result = GLOBUS_GSI_SYSCONFIG_GET_HOME_DIR(&home, &status);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+            home = NULL;
+            goto done;
+        }
+        
+        if(home && status == GLOBUS_FILE_DIR)
+        {
+            result = globus_i_gsi_sysconfig_create_cert_string(
+                service_cert,
+                & local_service_cert,
+                & status,
+                "%s%s%s%s%s%s%s",
+                home,
+                FILE_SEPERATOR,
+                X509_LOCAL_CERT_DIR,
+                FILE_SEPERATOR,
+                service_name,
+                FILE_SEPERATOR,
+                service_name,
+                X509_CERT_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+                goto done;
+            }
+            
+            result = globus_i_gsi_sysconfig_create_key_string(
+                service_key,
+                & local_service_key,
+                & status,
+                "%s%s%s%s%s%s%s%s",
+                home,
+                FILE_SEPERATOR,
+                X509_LOCAL_CERT_DIR,
+                FILE_SEPERATOR,
+                service_name,
+                FILE_SEPERATOR,
+                service_name,
+                X509_KEY_SUFFIX);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_STRING);
+                goto done;
+            }
+
+            if(*service_cert && !*service_key)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("Service certificate was found at: %s, but no "
+                     "service key was found at: %s",
+                     *service_cert, local_service_key));
+                goto done;
+            }
+
+            if(!*service_cert && *service_key)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_KEY_STRING,
+                    ("Service key was found at: %s, but no "
+                     "service certificate was found at: %s",
+                     *service_key, local_service_cert));
+                goto done;
+            }            
+        }
+        else
+        {
+            globus_object_t *           error_obj;
+            error_obj = globus_error_get(result);
+            globus_object_free(error_obj);
+        }
+    }
+
+    if(!(*service_cert) || !(*service_key))
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CERT_FILENAME,
+            ("\nThe service cert could not be found in: \n"
+             "1) env. var. X509_USER_CERT=%s\n"
+             "2) %s\n3) %s\n4) %s\n\n"
+             "The service key could not be found in:\n"
+             "1) env. var. X509_USER_KEY=%s\n"
+             "2) %s\n3) %s\n4) %s\n",
+             env_service_cert ? env_service_cert : "NULL",
+             default_service_cert ? default_service_cert : "NULL",
+             installed_service_cert ? installed_service_cert : "NULL",
+             local_service_cert ? local_service_cert : "NULL",
+             env_service_key ? env_service_key : "NULL",
+             default_service_key ? default_service_key : "NULL",
+             installed_service_key ? installed_service_key : "NULL",
+             local_service_key ? local_service_key : "NULL"));
+
+        goto done;
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_FPRINTF(
+        2, (stderr, "Using x509_user_cert=%s\n      x509_user_key =%s\n",
+            *service_cert , *service_key));
+
+    result = GLOBUS_SUCCESS;
+
+ done:
+
+    if(env_service_cert && env_service_cert != *service_cert)
+    {
+        globus_libc_free(env_service_cert);
+    }
+    if(env_service_key && env_service_key != *service_key)
+    {
+        globus_libc_free(env_service_key);
+    }
+    if(installed_service_cert && installed_service_cert != *service_cert)
+    {
+        globus_libc_free(installed_service_cert);
+    }
+    if(installed_service_key && installed_service_key != *service_key)
+    {
+        globus_libc_free(installed_service_key);
+    }
+    if(local_service_cert && local_service_cert != *service_cert)
+    {
+        globus_libc_free(local_service_cert);
+    }
+    if(local_service_key && local_service_key != *service_key)
+    {
+        globus_libc_free(local_service_key);
+    }
+    if(default_service_cert && default_service_cert != *service_cert)
+    {
+        globus_libc_free(default_service_cert);
+    }
+    if(default_service_key && default_service_key != *service_key)
+    {
+        globus_libc_free(default_service_key);
+    }
+
+    if(home)
+    {
+        free(home);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * UNIX - Get Proxy Filename
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the proxy cert filename based on the following
+ * search order:
+ * 
+ * <ol>
+ * <li> X509_USER_PROXY environment variable - This environment variable
+ * is set by the at run time for the specific application.  If
+ * the proxy_file_type variable is set to GLOBUS_PROXY_OUTPUT
+ *  (a proxy filename for writing is requested), 
+ * and the X509_USER_PROXY is set, this will be the 
+ * resulting value of the user_proxy filename string passed in.  If the
+ * proxy_file_type is set to GLOBUS_PROXY_INPUT and X509_USER_PROXY is 
+ * set, but the file it points to does not exist, 
+ * or has some other readability issues, the 
+ * function will continue checking using the other methods available.
+ * 
+ * <li> Check the default location for the proxy file of /tmp/x509_u<user_id>
+ * where <user id> is some unique string for that user on the host
+ * </ol>
+ *
+ * @param user_proxy
+ *        the proxy filename of the user
+ *
+ * @return
+ *        GLOBUS_SUCCESS or an error object identifier
+ */
+globus_result_t
+globus_gsi_sysconfig_get_proxy_filename_unix(
+    char **                             user_proxy,
+    globus_gsi_proxy_file_type_t        proxy_file_type)
+{
+    char *                              env_user_proxy = NULL;
+    char *                              env_value = NULL;
+    char *                              default_user_proxy = NULL;
+    globus_result_t                     result;
+    char *                              user_id_string = NULL;
+    globus_gsi_statcheck_t              status;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_proxy_filename_unix";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *user_proxy = NULL;
+    
+    if((env_value = getenv(X509_USER_PROXY)))
+    {
+        result = globus_i_gsi_sysconfig_create_key_string(
+            user_proxy,
+            & env_user_proxy,
+            & status,
+            env_value);
+        if(proxy_file_type == GLOBUS_PROXY_FILE_OUTPUT &&
+           status == GLOBUS_FILE_DOES_NOT_EXIST)
+        {
+            globus_object_t *           error_obj;
+            error_obj = globus_error_get(result);
+            globus_object_free(error_obj);
+            
+            *user_proxy = env_user_proxy;
+            status = GLOBUS_FILE_VALID;
+        }
+
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PROXY_FILENAME);
+            goto done;
+        }
+        
+        if(status != GLOBUS_FILE_VALID || !*user_proxy)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PROXY_FILENAME,
+                (X509_USER_PROXY"=%s %s",
+                 env_user_proxy,
+                 globus_l_gsi_sysconfig_status_strings[status]));
+            goto done;
+        }
+    }
+    
+    /* check if the proxy file type is for writing */
+    if(!(*user_proxy) && env_user_proxy && 
+       proxy_file_type == GLOBUS_PROXY_FILE_OUTPUT)
+    {
+        *user_proxy = env_user_proxy;
+    }
+
+    if (!*user_proxy)
+    {
+        result = GLOBUS_GSI_SYSCONFIG_GET_USER_ID_STRING(&user_id_string);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PROXY_FILENAME);
+            goto done;
+        }
+
+        result = globus_i_gsi_sysconfig_create_key_string(
+            user_proxy,
+            & default_user_proxy,
+            & status,
+            "%s%s%s%s",
+            DEFAULT_SECURE_TMP_DIR,
+            FILE_SEPERATOR,
+            X509_USER_PROXY_FILE,
+            user_id_string);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PROXY_FILENAME);
+            goto done;
+        }
+    }
+
+    if(!(*user_proxy) && 
+       default_user_proxy && 
+       proxy_file_type == GLOBUS_PROXY_FILE_OUTPUT)
+    {
+        *user_proxy = default_user_proxy;
+    }
+
+    if(!(*user_proxy))
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT( 
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_PROXY_FILENAME,
+            ("A file location for%s the proxy cert could not be found in: \n"
+             "1) env. var. X509_USER_PROXY=%s\n"
+             "2) %s\n",
+             (proxy_file_type == GLOBUS_PROXY_FILE_INPUT) ? "" : " writing",
+             env_user_proxy ? env_user_proxy : "NULL",
+             default_user_proxy ? default_user_proxy : "NULL"));
+        
+        goto done;
+    }
+    
+    result = GLOBUS_SUCCESS;
+
+ done:
+
+    if(user_id_string)
+    {
+        free(user_id_string);
+    }
+
+    if(default_user_proxy && (default_user_proxy != (*user_proxy)))
+    {
+        globus_libc_free(default_user_proxy);
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * @name UNIX - Get Signing Policy Filename
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Get the Signing Policy Filename on the current system,
+ * based on the CA's subject name, and the trusted certificates
+ * directory
+ *
+ * @param ca_name
+ *        The X509 subject name of the CA to get the signing policy of.
+ *        The hash of the CA is generated from this
+ *
+ * @param cert_dir
+ *        The trusted CA certificates directory, containing the singing_policy
+ *        files of the trusted CA's.
+ *
+ * @param singing_policy_filename
+ *        The resulting singing_policy filename
+ * @return 
+ *        GLOBUS_SUCCESS if no error occurred, otherwise an error object ID
+ */
+globus_result_t
+globus_gsi_sysconfig_get_signing_policy_filename_unix(
+    X509_NAME *                         ca_name,
+    char *                              cert_dir,
+    char **                             signing_policy_filename)
+{
+    char *                              signing_policy = NULL;
+    globus_gsi_statcheck_t              status;
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    unsigned long                       hash;
+    char *                              ca_cert_dir = NULL;
+    
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_signing_policy_filename_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    *signing_policy_filename = NULL;
+
+    if (cert_dir == NULL)
+    {
+        result = GLOBUS_GSI_SYSCONFIG_GET_CERT_DIR(&ca_cert_dir);
+        if(result != GLOBUS_SUCCESS)
+        {
+            GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                result,
+                GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_SIGNING_POLICY);
+            goto exit;
+        }
+    }
+    else
+    {
+        ca_cert_dir = cert_dir;
+    }
+
+    if(ca_name == NULL)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_SIGNING_POLICY,
+            ("NULL parameter ca_name passed to: %s", _function_name_));
+        goto exit;
+    }
+
+    hash = X509_NAME_hash(ca_name);
+
+    signing_policy = globus_gsi_cert_utils_create_string(
+        "%s%s%08lx%s", 
+        ca_cert_dir, FILE_SEPERATOR, hash, SIGNING_POLICY_FILE_EXTENSION);
+    
+    if(signing_policy == NULL)
+    {
+        result = GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+        goto exit;
+    }
+
+    result = GLOBUS_GSI_SYSCONFIG_FILE_EXISTS(signing_policy, &status);
+    if(result != GLOBUS_SUCCESS)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_SIGNING_POLICY);
+        goto exit;
+    }
+
+    if(status == GLOBUS_FILE_VALID)
+    {
+        *signing_policy_filename = signing_policy;
+    }
+
+ exit:
+
+    if(ca_cert_dir != NULL &&
+       cert_dir == NULL)
+    {
+        free(ca_cert_dir);
+    }
+
+    if(signing_policy != NULL &&
+       result != GLOBUS_SUCCESS)
+    {
+        free(signing_policy);
+        *signing_policy_filename = NULL;
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * @name UNIX - Get CA Cert Filenames
+ * @ingroup globus_gsi_sysconfig_unix
+ */
+/* @{ */
+/**
+ * Gets a list of trusted CA certificate filenames in 
+ * a trusted CA certificate directory.  
+ *
+ * @param ca_cert_dir
+ *        The trusted CA certificate directory to get the filenames from
+ * @param ca_cert_list
+ *        The resulting list of CA certificate filenames.  This is a
+ *        a globus list structure.  
+ *        @see globus_fifo_t
+ * @return
+ *        GLOBUS_SUCCESS if no error occurred, otherwise an error object ID
+ *        is returned
+ */ 
+globus_result_t
+globus_gsi_sysconfig_get_ca_cert_files_unix(
+    char *                              ca_cert_dir,
+    globus_fifo_t *                     ca_cert_list)
+{
+    DIR *                               dir_handle = NULL;
+    struct dirent *                     tmp_entry = NULL;
+    int                                 file_length;
+    char *                              full_filename_path = NULL;
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_ca_cert_file_unix";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    if(!ca_cert_dir)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CA_CERT_FILENAMES,
+            ("NULL parameter ca_cert_dir passed to function: %s",
+             _function_name_));
+        goto exit;
+    }
+
+    if(!ca_cert_list)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CA_CERT_FILENAMES,
+            ("NULL parameter ca_cert_list passed to function: %s",
+             _function_name_));
+        goto exit;
+    }
+
+    dir_handle = globus_libc_opendir(ca_cert_dir);
+    if(dir_handle == NULL)
+    {
+        result = globus_error_put(
+            globus_error_wrap_errno_error(
+                GLOBUS_GSI_SYSCONFIG_MODULE,
+                errno,
+                GLOBUS_GSI_SYSCONFIG_ERROR_ERRNO,
+                "Error opening directory: %s", ca_cert_dir));
+        goto exit;
+    }
+
+    while(globus_libc_readdir_r(dir_handle,&tmp_entry) == 0 &&
+          tmp_entry != NULL)
+    {
+        file_length = strlen(tmp_entry->d_name);
+        /* check the following:
+         * 
+         * - file length is greater than or equal to 10
+         * - first 8 characters are alpha-numeric
+         * - 9th character is '.'
+         * - characters after the '.' are numeric
+         */
+        if(file_length >= (X509_HASH_LENGTH + 2) &&
+           (*(tmp_entry->d_name + X509_HASH_LENGTH) == '.') &&
+           (strspn(tmp_entry->d_name, "0123456789abcdefABCDEF") 
+            == X509_HASH_LENGTH) &&
+           (strspn((tmp_entry->d_name + (X509_HASH_LENGTH + 1)), 
+                   "0123456789") == (file_length - 9)))
+        {
+            full_filename_path = 
+                globus_gsi_cert_utils_create_string(
+                    "%s%s%s", ca_cert_dir, FILE_SEPERATOR, tmp_entry->d_name);
+            
+            if(full_filename_path == NULL)
+            {
+                globus_free(tmp_entry);
+                while((full_filename_path =
+                       (char *) globus_fifo_dequeue(ca_cert_list)) != NULL)
+                {
+                    free(full_filename_path);
+                }
+                GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_CA_CERT_FILENAMES,
+                    ("Couldn't get full pathname for CA cert"));
+                goto exit;
+            }
+
+            globus_fifo_enqueue(ca_cert_list, (void *)full_filename_path);
+        }
+
+        globus_free(tmp_entry);    
+    }
+
+ exit:
+
+    if(dir_handle != NULL)
+    {
+        globus_libc_closedir(dir_handle);
+    }
+
+    if(tmp_entry != NULL)
+    {
+	globus_libc_free(tmp_entry);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+
+}
+/* @} */
+
+globus_result_t
+globus_gsi_sysconfig_remove_all_owned_files_unix(
+    char *                              default_filename)
+{
+    struct stat                         stx;
+    char *                              full_filename = NULL;
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    DIR *                               secure_tmp_dir = NULL;
+    struct dirent *                     dir_entry = NULL;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_remove_all_proxy_files_unix";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    secure_tmp_dir = globus_libc_opendir(DEFAULT_SECURE_TMP_DIR);
+    if(!secure_tmp_dir)
+    {
+        result = globus_error_put(
+            globus_error_wrap_errno_error(
+                GLOBUS_GSI_SYSCONFIG_MODULE,
+                errno,
+                GLOBUS_GSI_SYSCONFIG_ERROR_ERRNO,
+                __FILE__":%d:%s: Error opening directory: %s\n",
+                __LINE__,
+                _function_name_, 
+                DEFAULT_SECURE_TMP_DIR));
+        goto exit;
+    }
+
+    while(globus_libc_readdir_r(secure_tmp_dir, &dir_entry) == 0 &&
+          dir_entry != NULL)
+    {
+        if((default_filename && 
+            !strcmp(dir_entry->d_name, default_filename)) ||
+           !strncmp(dir_entry->d_name,
+                    X509_UNIQUE_PROXY_FILE,
+                    strlen(X509_UNIQUE_PROXY_FILE)))
+        {
+            full_filename = globus_gsi_cert_utils_create_string(
+                "%s%s%s",
+                DEFAULT_SECURE_TMP_DIR,
+                FILE_SEPERATOR,
+                dir_entry->d_name);
+
+            if(stat(full_filename, &stx) == -1)
+            {
+                globus_free(dir_entry);
+                continue;
+            }
+
+            RAND_add((void *) &stx, sizeof(stx), 2);
+                    
+            if(stx.st_uid == getuid())
+            {
+                static char             msg[65]
+                    = "DESTROYED BY GLOBUS\r\n";
+                int                     f = open(full_filename, O_RDWR);
+                int                     size, rec, left;
+                if (f) 
+                {
+                    size = lseek(f, 0L, SEEK_END);
+                    lseek(f, 0L, SEEK_SET);
+                    if (size > 0) 
+                    {
+                        rec = size / 64;
+                        left = size - rec * 64;
+                        while (rec)
+                        {
+                            write(f, msg, 64);
+                            rec--;
+                        }
+                        if (left)
+                        { 
+                            write(f, msg, left);
+                        }
+                    }
+                    close(f);
+                }
+                remove(full_filename);
+            }
+
+            free(full_filename);
+        }
+        globus_free(dir_entry);
+    }
+
+ exit:
+
+    if(secure_tmp_dir != NULL)
+    {
+        globus_libc_closedir(secure_tmp_dir);
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+/**
+ * @name 
+ * @ingroup
+ */
+globus_result_t
+globus_gsi_sysconfig_is_superuser_unix(
+    int *                               is_superuser)
+{
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_is_superuser_unix";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    if(getuid() == 0)
+    {
+        *is_superuser = 1;
+    }
+    else
+    {
+        *is_superuser = 0;
+    }
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return GLOBUS_SUCCESS;
+}
+/* @} */
+
+globus_result_t
+globus_gsi_sysconfig_get_gridmap_filename_unix(
+    char **                             filename)
+{
+    char *                              home_dir = NULL;
+    char *                              gridmap_env = NULL;
+    char *                              gridmap_filename = NULL;
+    globus_gsi_statcheck_t              status;
+    globus_result_t                     result = GLOBUS_SUCCESS;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_gridmap_filename_unix";
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    if(((gridmap_env = (char *) getenv("GRIDMAP"))   != NULL) ||
+       ((gridmap_env = (char *) getenv("GLOBUSMAP")) != NULL) ||
+       ((gridmap_env = (char *) getenv("globusmap")) != NULL) ||
+       ((gridmap_env = (char *) getenv("GlobusMap")) != NULL))
+    {
+        gridmap_filename = globus_gsi_cert_utils_create_string(
+            "%s",
+            gridmap_env);
+        if(!gridmap_filename)
+        {
+            GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+            goto exit;
+        }
+    }
+
+    if(!gridmap_filename)
+    {
+        if(getuid() == 0)
+        {
+            /* being run as root */
+            
+            gridmap_filename = globus_gsi_cert_utils_create_string(
+                "%s",
+                DEFAULT_GRIDMAP);
+            if(!gridmap_filename)
+            {
+                GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+                goto exit;
+            }
+        }
+        else
+        {
+            result = GLOBUS_GSI_SYSCONFIG_GET_HOME_DIR(&home_dir, &status);
+            if(result != GLOBUS_SUCCESS)
+            {
+                GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+                    result,
+                    GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_GRIDMAP_FILENAME);
+                goto exit;
+            }
+            
+            if(home_dir && status == GLOBUS_FILE_DIR)
+            {
+                gridmap_filename = globus_gsi_cert_utils_create_string(
+                    "%s%s%s",
+                    home_dir,
+                    FILE_SEPERATOR,
+                    LOCAL_GRIDMAP);
+                if(!gridmap_filename)
+                {
+                    GLOBUS_GSI_SYSTEM_CONFIG_MALLOC_ERROR;
+                    goto exit;
+                }
+            }
+        }
+    }
+
+    if(!gridmap_filename)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_GRIDMAP_FILENAME,
+            ("A valid gridmap file could not be found."));
+        goto exit;
+    }
+
+    *filename = gridmap_filename;
+
+ exit:
+
+    if(home_dir != NULL)
+    {
+        free(home_dir);
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+/* @} */
+
+#endif /* done defining *_unix functions */
+
+/**
+ * Get Unique Proxy Filename
+ * @ingroup globus_gsi_sysconfig
+ */
+/* @{ */
+/**
+ * Get a unique proxy cert filename.  This is mostly used
+ * for delegated proxy credentials.  Each filename returned
+ * is going to be unique for each time the function is called.
+ * 
+ * @param unique_filename
+ *        the unique filename for a delegated proxy cert
+ *
+ * @return
+ *        GLOBUS_SUCCESS or an error object identifier
+ */
+globus_result_t
+globus_gsi_sysconfig_get_unique_proxy_filename(
+    char **                             unique_filename)
+{
+    char *                              default_unique_filename = NULL;
+    globus_result_t                     result;
+    char *                              proc_id_string = NULL;
+    char                                unique_tmp_name[L_tmpnam];
+    char *                              unique_postfix = NULL;
+    static int                          i = 0;
+    globus_gsi_statcheck_t              status;
+    static char *                       _function_name_ =
+        "globus_gsi_sysconfig_get_unique_proxy_filename";
+
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER;
+
+    memset(unique_tmp_name, 0, L_tmpnam);
+    
+    *unique_filename = NULL;
+
+    result = GLOBUS_GSI_SYSCONFIG_GET_PROC_ID_STRING(&proc_id_string);
+    if(result != GLOBUS_SUCCESS)
+    {
+        proc_id_string = NULL;
+        GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_DELEG_FILENAME);
+        goto done;
+    }
+
+    if(tmpnam(unique_tmp_name) == NULL)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_DELEG_FILENAME,
+            ("Could not get a unique filename for the temporary proxy cert"));
+        goto done;
+    }
+    
+    unique_postfix = strrchr(unique_tmp_name, '/');
+    ++unique_postfix;
+
+    if((result = globus_i_gsi_sysconfig_create_key_string(
+            unique_filename,
+            & default_unique_filename,
+            & status,
+            "%s%s%s%s.%s.%d",
+            DEFAULT_SECURE_TMP_DIR,
+            FILE_SEPERATOR,
+            X509_UNIQUE_PROXY_FILE,
+            proc_id_string,
+            unique_postfix,
+            ++i)) != GLOBUS_SUCCESS)
+    {
+        GLOBUS_GSI_SYSCONFIG_ERROR_CHAIN_RESULT(
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_DELEG_FILENAME);
+        goto done;
+    }
+
+    *unique_filename = default_unique_filename;
+
+    if(!(*unique_filename))
+    {            
+        GLOBUS_GSI_SYSCONFIG_ERROR_RESULT( 
+            result,
+            GLOBUS_GSI_SYSCONFIG_ERROR_GETTING_DELEG_FILENAME,
+            ("A file location for writing the unique proxy cert"
+             " could not be found in: %s\n",
+             default_unique_filename));
+        
+        goto done;
+    }
+
+    result = GLOBUS_SUCCESS;
+
+ done:
+
+    if(default_unique_filename && 
+       (default_unique_filename != (*unique_filename)))
+    {
+        globus_libc_free(default_unique_filename);
+    }
+
+    if(proc_id_string != NULL)
+    {
+        free(proc_id_string);
+    }
+    
+    GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT;
+    return result;
+}
+
+/* @} */
+
+#endif
diff --git a/main/src/ssh2rpd.cxx b/main/src/ssh2rpd.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a7b41bebe6b07b7ade300cb54c27785e6e0b26c1
--- /dev/null
+++ b/main/src/ssh2rpd.cxx
@@ -0,0 +1,106 @@
+// @(#)root/main:$Name:  $:$Id: rmain.cxx,v 1.6 2002/05/10 08:30:06 brun Exp $
+// Author: Gerardo Ganis    1/7/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// ssh2rpd                                                              //
+//                                                                      //
+// Small program to communicate successful result of sshd auth to the   //
+// relevant rootd and proofd daemons                                    //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include "Varargs.h"
+
+
+const int  kMAXPATHLEN    = 1024;
+char      *gFileLog       = 0;
+int        gDebug         = 0;
+
+//______________________________________________________________________________
+void Info(const char *va_(fmt), ...)
+{
+   // Write info message to syslog.
+
+   char    buf[1024];
+   va_list ap;
+
+   va_start(ap,va_(fmt));
+   vsprintf(buf, fmt, ap);
+   va_end(ap);
+
+   if (gFileLog != 0 && strlen(gFileLog) > 0) {
+      FILE *fl= fopen(gFileLog,"a");
+      fprintf(fl, "%s",buf);
+      fclose(fl);
+   } else {
+      syslog(LOG_INFO, buf);
+   }
+}
+
+//______________________________________________________________________________
+int main(int argc, char **argv)
+{
+   char *Pipe = 0; int ProId=-1, RemId=-1;
+
+   if (argc < 2) {
+      Info("ssh2rpd: argc=%d : at least one additional argument required - exit\n", argc);
+      exit(1);
+   }
+
+   // Parse Arguments
+   gDebug = atoi(argv[1]);
+   if (argc > 2) Pipe     = strdup(argv[2]);
+   if (argc > 3) ProId    = atoi(argv[3]);
+   if (argc > 4) RemId    = atoi(argv[4]);
+   if (argc > 5) gFileLog = strdup(argv[5]);
+
+
+   if (gDebug > 0)
+      Info("ssh2rpd: forked with args: %d %s %d %d '%s'\n",gDebug,Pipe,ProId,RemId,gFileLog);
+
+   // Preparing socket connection
+   struct sockaddr_un servAddr;
+   servAddr.sun_family = AF_UNIX;
+   strcpy(servAddr.sun_path,Pipe);
+   int sd;
+   if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+      Info("ssh2rpd: cannot open socket: exiting ");
+      exit(1);
+   }
+   // Connecting to socket
+   int rc;
+   if ((rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr))) < 0) {
+      Info("ssh2rpd: cannot connect socket: exiting (errno= %d)",errno);
+      exit(1);
+   }
+
+   // Sending "OK" ...
+   char *okbuf = "OK";
+   rc = send(sd, okbuf, strlen(okbuf), 0);
+   if (rc != (int)strlen(okbuf)) {
+      Info("ssh2rpd: sending might have been unsuccessful (bytes send: %d)",rc);
+   }
+
+   if (Pipe != 0) free(Pipe);
+   if (gFileLog != 0) free(gFileLog);
+
+   exit(0);
+}
diff --git a/net/inc/NetErrors.h b/net/inc/NetErrors.h
new file mode 100644
index 0000000000000000000000000000000000000000..4dd55bf78e973bd2d33e8e0b76f2e1431cdab581
--- /dev/null
+++ b/net/inc/NetErrors.h
@@ -0,0 +1,58 @@
+// @(#)root/net:$Name:$:$Id:$
+// Author: Fons Rademakers   11/08/97
+
+/*************************************************************************
+ * Copyright (C) 1995-2003, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_NetErrors
+#define ROOT_NetErrors
+
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// NetErrors                                                            //
+//                                                                      //
+// This header file defines error codes generated by rootd/proofd.      //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef ROOT_Rtypes
+#include "Rtypes.h"
+#endif
+
+enum ERootdErrors {
+   kErrUndef,
+   kErrNoFile,
+   kErrBadFile,
+   kErrFileExists,
+   kErrNoAccess,
+   kErrFileOpen,
+   kErrFileWriteOpen,
+   kErrFileReadOpen,
+   kErrNoSpace,
+   kErrBadOp,
+   kErrBadMess,
+   kErrFilePut,
+   kErrFileGet,
+   kErrNoUser,
+   kErrNoAnon,
+   kErrBadUser,
+   kErrNoHome,
+   kErrNoPasswd,
+   kErrBadPasswd,
+   kErrNoSRP,
+   kErrFatal,
+   kErrRestartSeek,
+   kErrNotAllowed,
+   kErrConnectionRefused,
+   kErrAuthNotOK
+};
+
+R__EXTERN const char *gRootdErrStr[];
+
+#endif
diff --git a/net/inc/TAuthDetails.h b/net/inc/TAuthDetails.h
new file mode 100644
index 0000000000000000000000000000000000000000..611be13b1e5a54af8771cc1dbe08812aa2183ff5
--- /dev/null
+++ b/net/inc/TAuthDetails.h
@@ -0,0 +1,80 @@
+// @(#)root/net:$Name:  $:$Id: TInetAddress.h,v 1.4 2001/10/01 09:46:32 rdm Exp $
+// Author: G. Ganis   31/03/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_TAuthDetails
+#define ROOT_TAuthDetails
+
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TAuthDetails                                                         //
+//                                                                      //
+// Contains details about successful authentications                    //
+// Used by THostAuth                                                    //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef ROOT_TObject
+#include "TObject.h"
+#endif
+#ifndef ROOT_TString
+#include "TString.h"
+#endif
+#ifndef ROOT_TAuthenticate
+#include "TAuthenticate.h"
+#endif
+
+class TAuthDetails : public TObject {
+
+public:
+   enum EService { kROOTD=1, kPROOFD };
+
+private:
+   TString      fHost;                // Remote host and service (in form  host:port:service)
+   TString      fRealHost;            // Remote host name
+   Int_t        fPort;                // Remote Port number
+   EService     fService;             // Remote Service flag
+   Int_t        fMethod;              // Authentication method used
+   Int_t        fRemoteOffSet;        // offset in remote host auth tab file (in bytes)
+   TString      fRemoteLogin;         // Remote login name (either auth user or one of the available anonymous)
+   TString      fDetails;             // Details for the auth process (user, principal, ... )
+   Bool_t       fReUse;               // Determines if established authentication context should be reused
+   TString      fToken;               // Token identifying this authentication
+   Int_t        fRSAKey;              // Type of RSA key used
+
+public:
+
+   TAuthDetails(const char *host, Int_t meth, Int_t offset, Bool_t reuse,
+                const char *details, const char *token, Int_t key,
+                const char *login = "");
+   virtual ~TAuthDetails() { }
+
+   const char *GetHost()    const;
+   Int_t       GetPort()    const;
+   Int_t       GetService() const;
+   Int_t       GetMethod()  const { return fMethod; }
+   const char *GetDetails() const { return fDetails; }
+   Bool_t      GetReUse()   const { return fReUse; }
+   const char *GetLogin()   const { return fRemoteLogin; }
+   Int_t       GetOffSet()  const { return fRemoteOffSet; }
+   const char *GetToken()   const { return fToken; }
+   Int_t       GetRSAKey()  const { return fRSAKey; }
+
+   void     SetOffSet(Int_t offset)      { fRemoteOffSet = offset; }
+   void     SetReUse(Bool_t reuse)       { fReUse        = reuse; }
+   void     SetLogin(const char *login)  { fRemoteLogin  = login; }
+
+   void     Print(Option_t *option = "") const;
+
+   ClassDef(TAuthDetails,0)  // Class providing host specific authentication information
+};
+
+#endif
diff --git a/net/inc/THostAuth.h b/net/inc/THostAuth.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c9be58280469883347588d88cdb506c71db5815
--- /dev/null
+++ b/net/inc/THostAuth.h
@@ -0,0 +1,81 @@
+// @(#)root/net:$Name:  $:$Id: TInetAddress.h,v 1.4 2001/10/01 09:46:32 rdm Exp $
+// Author: G. Ganis   19/03/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_THostAuth
+#define ROOT_THostAuth
+
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// THostAuth                                                            //
+//                                                                      //
+// Contains details about host-specific authentication methods and the  //
+// result of their application                                          //
+// Used by TAuthenticate                                                //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef ROOT_TObject
+#include "TObject.h"
+#endif
+#ifndef ROOT_TString
+#include "TString.h"
+#endif
+#ifndef ROOT_TList
+#include "TList.h"
+#endif
+
+
+class THostAuth : public TObject {
+
+private:
+   TString      fHost;         // Host
+   TString      fUser;         // Username
+   Int_t        fNumMethods;   // Number of AuthMethods
+   Int_t       *fMethods;      // AuthMethods
+   TString     *fDetails;      // AuthDetails
+
+   TList       *fEstablished;  // List of (TAuthDetails) established authentications
+
+public:
+
+   THostAuth();
+   THostAuth(const char *host, const char *user, Int_t nmeth, Int_t *authmeth, char **details);
+   THostAuth(const char *host, const char *user, Int_t authmeth, char *details);
+   virtual ~THostAuth();
+
+   Int_t    NumMethods() const { return fNumMethods; }
+   Int_t    GetMethods(Int_t meth) const { return fMethods[meth]; }
+   void     AddMethod(Int_t level, char *details);
+   void     RemoveMethod(Int_t level);
+   void     ReOrder(Int_t nmet, Int_t *fmet);
+   void     SetFirst(Int_t method);
+   void     SetFirst(Int_t level, char *details);
+
+   const char *GetDetails(Int_t level);
+   void        SetDetails(Int_t level, char *details);
+
+   const char *GetHost() const { return fHost; }
+   const char *GetUser() const { return fUser; }
+
+   void     SetHost(const char *host) { fHost = host; }
+   void     SetUser(const char *user) { fUser = user; }
+
+   TList   *Established() const { return fEstablished; }
+
+   void     Print(Option_t *option = "") const;
+   void     Print(const char *proc);
+   void     PrintEstablished();
+
+   ClassDef(THostAuth,0)  // Class providing host specific authentication information
+};
+
+#endif
diff --git a/net/src/NetErrors.cxx b/net/src/NetErrors.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4903231d3070d463047ab8b58b5f2ed0d688ce6f
--- /dev/null
+++ b/net/src/NetErrors.cxx
@@ -0,0 +1,50 @@
+// @(#)root/net:$Name:$:$Id:$
+// Author: Fons Rademakers   28/08/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2003, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// NetErrors                                                            //
+//                                                                      //
+// This file defines error strings mapped to the error codes generated  //
+// by rootd/proofd.                                                     //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include "NetErrors.h"
+
+// Must match order of ERootdErrors enum in NetErrors.h
+const char *gRootdErrStr[] = {
+   "undefined error",
+   "file not found",
+   "error in file name",
+   "file already exists",
+   "no access to file",
+   "error opening file",
+   "file already opened in read or write mode",
+   "file already opened in write mode",
+   "no more space on device",
+   "bad op code",
+   "bad message",
+   "error writing to file",
+   "error reading from file",
+   "no such user",
+   "remote not setup for anonymous access",
+   "illegal user name",
+   "can't cd to home directory",
+   "can't get passwd info",
+   "wrong passwd",
+   "no SRP support in remote daemon",
+   "fatal error",
+   "cannot seek to restart position",
+   "server does not accept the requested authentication method from this host or from user@host",
+   "server does not accept connection from this host: contact server administrator",
+   "authentication attempt unsuccessful"
+};
diff --git a/net/src/TAuthDetails.cxx b/net/src/TAuthDetails.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a00f1fc3fe1e682bb5139bfa2d8549d8efbb3cc5
--- /dev/null
+++ b/net/src/TAuthDetails.cxx
@@ -0,0 +1,122 @@
+// @(#)root/net:$Name:  $:$Id: TInetAddress.h,v 1.4 2001/10/01 09:46:32 rdm Exp $
+// Author: G. Ganis   19/03/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TAuthDetails                                                         //
+//                                                                      //
+// Contains details about successful authentications                    //
+// Used by THostAuth                                                    //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#ifdef HAVE_CONFIG
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#include "TAuthDetails.h"
+
+ClassImp(TAuthDetails)
+
+//______________________________________________________________________________
+TAuthDetails::TAuthDetails(const char *host, Int_t meth, Int_t offset,
+                           Bool_t reuse, const char *details, const char *token,
+                           Int_t key, const char *login)
+{
+   // Create authdetails object.
+
+   fHost         = host;  // contains also info about remote port and service
+   fPort         = -2;
+   fService      = (EService) 0;
+   fMethod       = meth;
+   fRemoteOffSet = offset;
+   fRemoteLogin  = login;
+   fDetails      = details;
+   fReUse        = reuse;
+   fToken        = token;
+   fRSAKey       = key;
+}
+
+//______________________________________________________________________________
+const char *TAuthDetails::GetHost() const
+{
+  // Return remote host name.
+
+   if (fRealHost == "") {
+      const_cast<TAuthDetails*>(this)->fRealHost = fHost;
+      if (fRealHost.Index(":") != kNPOS)
+         const_cast<TAuthDetails*>(this)->fRealHost.Remove(fRealHost.Index(":"));
+   }
+
+   return fRealHost;
+}
+
+//______________________________________________________________________________
+Int_t TAuthDetails::GetPort() const
+{
+  // Return remote port. Returns -1 if port not found.
+
+   if (fPort == -2) {
+      Int_t f = fHost.First(':');
+      Int_t l = fHost.Last(':');
+      if (l == kNPOS || f == kNPOS || f == l) {
+         const_cast<TAuthDetails*>(this)->fPort = -1;
+         return fPort;
+      }
+      f++;
+      TString port = fHost(f, l-f);
+      const_cast<TAuthDetails*>(this)->fPort = atoi(port.Data());
+   }
+   return fPort;
+}
+
+//______________________________________________________________________________
+Int_t TAuthDetails::GetService() const
+{
+  // Return remote service flag, either kROOTD, kPROOFD or kUNKNOWN.
+
+   if (fService == 0) {
+      Int_t f = fHost.First(':');
+      Int_t l = fHost.Last(':');
+      if (l == kNPOS || f == kNPOS || f == l) {
+         const_cast<TAuthDetails*>(this)->fService = (EService)-1;
+         return fService;
+      }
+      l++;
+      TString service = fHost(l, fHost.Length()-1);
+      const_cast<TAuthDetails*>(this)->fService = (EService) atoi(service.Data());
+   }
+   return fService;
+}
+
+//______________________________________________________________________________
+void TAuthDetails::Print(Option_t *opt) const
+{
+   // Print object content. If option is "e" print "established details.
+
+   // Method names
+   const char *AuthMeth[kMAXSEC]= {"UsrPwd","SRP","Krb5","Globus","SSH","UidGid"};
+   const char *Service[3]= {" ","rootd","proofd"};
+
+   Int_t srv = (GetService() > 0 && GetService() < 3) ? GetService() : 0;
+
+   if (opt[0] == 'e') {
+      Info("PrintEstblshd","+ Method:%d (%s) OffSet:%d Login:%s ReUse:%d Port:%d Service:%s",
+          fMethod,AuthMeth[fMethod],fRemoteOffSet,fRemoteLogin.Data(),fReUse,GetPort(),Service[srv]);
+      Info("PrintEstblshd","+   Details:%s",fDetails.Data());
+   } else {
+      Info("Print","+ Host:%s Port:%d Service:%s Method:%d (%s) OffSet:%d Login:%s ReUse:%d Details:%s",
+           GetHost(),GetPort(),Service[srv],fMethod,AuthMeth[fMethod],fRemoteOffSet,fRemoteLogin.Data(),
+           fReUse,fDetails.Data());
+   }
+}
diff --git a/net/src/THostAuth.cxx b/net/src/THostAuth.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a595ab3e796ae7b68a75062d552c6327b02f1efc
--- /dev/null
+++ b/net/src/THostAuth.cxx
@@ -0,0 +1,404 @@
+// @(#)root/net:$Name:  $:$Id: TInetAddress.h,v 1.4 2001/10/01 09:46:32 rdm Exp $
+// Author: G. Ganis   19/03/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// THostAuth                                                            //
+//                                                                      //
+// Contains details about host-specific authentication methods and the  //
+// result of their application.                                         //
+// Used by TAuthenticate.                                               //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#ifdef HAVE_CONFIG
+#include "config.h"
+#endif
+
+#include "TSystem.h"
+#include "THostAuth.h"
+#include "TAuthDetails.h"
+
+
+ClassImp(THostAuth)
+
+//______________________________________________________________________________
+THostAuth::THostAuth(): TObject()
+{
+   // Default constructor
+
+   fHost        = "";
+   fUser        = "";
+   fNumMethods  = 0;
+   fMethods     = 0;
+   fDetails     = 0;
+   fEstablished = 0;
+}
+
+//______________________________________________________________________________
+THostAuth::THostAuth(const char *host, const char *user, Int_t nmeth,
+                     Int_t *authmeth, char **details)
+{
+   // Create hostauth object.
+
+   int i;
+
+   fHost = host;
+   // Check and save the host FQDN ...
+   TInetAddress addr = gSystem->GetHostByName(fHost);
+   if (addr.IsValid()) {
+      fHost = addr.GetHostName();
+      if (fHost == "UnNamedHost")
+         fHost = addr.GetHostAddress();
+   }
+   fUser = user;
+   if (fUser == "")
+      fUser = gSystem->Getenv("USER");
+   if (fUser == "") {
+      UserGroup_t *u = gSystem->GetUserInfo();
+      if (u)
+         fUser = u->fUser;
+      delete u;
+   }
+   fNumMethods = nmeth;
+   fMethods    = new Int_t[nmeth];
+   if (authmeth != 0) {
+      for (i = 0; i < nmeth; i++) { fMethods[i] = authmeth[i]; }
+   }
+   fDetails = new TString[nmeth];
+   if (details != 0) {
+      for (i = 0; i < nmeth; i++) {
+         if (details[i] != 0) fDetails[i] = details[i];
+      }
+   }
+   fEstablished = new TList;
+}
+
+//______________________________________________________________________________
+THostAuth::THostAuth(const char *host, const char *user, Int_t authmeth,
+                     char *details)
+{
+   // Create hostauth object with one method only.
+
+   fHost = host;
+    // Check and save the host FQDN ...
+   TInetAddress addr = gSystem->GetHostByName(fHost);
+   if (addr.IsValid()) {
+     fHost = addr.GetHostName();
+     if (fHost == "UnNamedHost")
+       fHost = addr.GetHostAddress();
+   }
+   fUser = user;
+   if (fUser == "")
+      fUser = gSystem->Getenv("USER");
+   if (fUser == "") {
+      UserGroup_t *u = gSystem->GetUserInfo();
+      if (u)
+         fUser = u->fUser;
+      delete u;
+   }
+   fNumMethods  = 1;
+   fMethods     = new Int_t[1];
+   fMethods[0]  = authmeth;
+   fDetails     = new TString[1];
+   if (details!=0)
+      fDetails[0] = details;
+   fEstablished = new TList;
+}
+
+//______________________________________________________________________________
+void  THostAuth::AddMethod(Int_t meth, char *details)
+{
+   // Add new method to the list.
+
+   int i;
+
+   // Save existing info
+   Int_t   *tMethods = new Int_t[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { tMethods[i] = fMethods[i]; }
+   TString *tDetails = new TString[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { tDetails[i] = fDetails[i]; }
+
+   // Resize arrays
+   delete [] fMethods;
+   delete [] fDetails;
+   fMethods = new Int_t[fNumMethods+1];
+   for (i = 0; i < fNumMethods; i++) { fMethods[i] = tMethods[i]; }
+   fDetails = new TString[fNumMethods+1];
+   for (i = 0; i < fNumMethods; i++) { fDetails[i] = tDetails[i]; }
+
+   // delete temporary arrays
+   delete [] tMethods;
+   delete [] tDetails;
+
+   // This is the new method
+   fMethods[fNumMethods] = meth;
+   fDetails[fNumMethods] = details;
+
+   // Increment total number
+   fNumMethods++;
+
+   if (gDebug > 3) Print();
+}
+
+//______________________________________________________________________________
+void  THostAuth::RemoveMethod(Int_t meth)
+{
+   // Remove method 'meth' from the list, if there ...
+
+   int i, k;
+
+   // Make sure we are not empty
+   if (fNumMethods == 0) return;
+
+   // Check if 'meth' is in the list
+   int j = -1;
+   for (i = 0; i < fNumMethods; i++) { if (fMethods[i] == meth) j = i; }
+   if (j == -1) return;
+
+   // Save existing info
+   Int_t   *tMethods = new Int_t[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { tMethods[i] = fMethods[i]; }
+   TString *tDetails = new TString[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { tDetails[i] = fDetails[i]; }
+
+   // Resize arrays
+   delete [] fMethods;
+   delete [] fDetails;
+   fMethods = new Int_t[fNumMethods-1];
+   fDetails = new TString[fNumMethods-1];
+   k = 0;
+   for (i = 0; i < fNumMethods; i++) {
+      if (tMethods[i] != meth) {
+         fMethods[k] = tMethods[i];
+         fDetails[k] = tDetails[i];
+         k++;
+      }
+   }
+   // delete temporary arrays
+   delete [] tMethods;
+   delete [] tDetails;
+
+   // Decrement total number
+   fNumMethods--;
+
+   if (gDebug > 3) Print();
+}
+
+//______________________________________________________________________________
+  THostAuth::~THostAuth()
+{
+   // The dtor.
+
+   delete [] fMethods;
+   delete [] fDetails;
+   delete    fEstablished;
+}
+
+//______________________________________________________________________________
+const char *THostAuth::GetDetails(Int_t level)
+{
+   // Return authentication details for specified level
+   // or "" if the specified level does not exist for this host.
+
+   int i;
+   for (i = 0; i < fNumMethods; i++) {
+      if (fMethods[i] == level) {
+         if (gDebug > 3) Info("GetDetails"," %d: returning fDetails[%d]: %s", level,i,fDetails[i].Data());
+         return fDetails[i];
+      }
+   }
+   static const char *empty = " ";
+   return empty;
+}
+
+//______________________________________________________________________________
+void THostAuth::SetDetails(Int_t level, char *details)
+{
+   // Set authentication details for specified level.
+
+   int i, jm=-1;
+   for (i = 0; i < fNumMethods; i++) {
+     if (fMethods[i] == level) { fDetails[i] = details; jm = i; break; }
+   }
+   // If not in the list, add new method ...
+   if (jm == -1) AddMethod(level, details);
+}
+
+//______________________________________________________________________________
+void THostAuth::Print(Option_t *) const
+{
+   // Print object content.
+
+   // Method names
+   const char *AuthMeth[kMAXSEC] = { "UsrPwd","SRP","Krb5","Globus","SSH","UidGid" };
+
+   Info("Print","+------------------------------------------------------------------+");
+   Info("Print","+ Host:%s - User:%s - # of available methods:%d",fHost.Data(),fUser.Data(),fNumMethods);
+   int i = 0;
+   for (i = 0; i < fNumMethods; i++) {
+      Info("Print","+ Method: %d (%s)  Details:%s",fMethods[i],AuthMeth[fMethods[i]],fDetails[i].Data());
+   }
+   Info("Print","+------------------------------------------------------------------+");
+}
+
+//______________________________________________________________________________
+void THostAuth::Print(const char *proc)
+{
+   // Print object content.
+
+   // Method names
+   const char *AuthMeth[kMAXSEC] = {"UsrPwd","SRP","Krb5","Globus","SSH","UidGid"};
+
+   Info("Print","%s +------------------------------------------------------------------+",proc);
+   Info("Print","%s + Host:%s - User:%s - # of available methods:%d",proc,fHost.Data(),fUser.Data(),fNumMethods);
+   int i = 0;
+   for (i = 0; i < fNumMethods; i++){
+      Info("Print","%s + Method: %d (%s)  Details:%s",proc,fMethods[i],AuthMeth[fMethods[i]],fDetails[i].Data());
+   }
+   Info("Print","%s +------------------------------------------------------------------+",proc);
+}
+
+//______________________________________________________________________________
+void THostAuth::PrintEstablished()
+{
+   // Print info about estalished authentication vis-a-vis of this Host.
+
+   Info("PrintEstablished","+------------------------------------------------------------------------------+");
+   Info("PrintEstablished","+ Host:%s - Number of Established Authentications: %d",fHost.Data(),fEstablished->GetSize());
+
+   // Check list
+   if (fEstablished->GetSize()>0) {
+      TIter next(fEstablished);
+      TAuthDetails *ai;
+      while ((ai = (TAuthDetails*) next()))
+         ai->Print("e");
+   }
+   Info("PrintEstablished","+------------------------------------------------------------------------------+");
+}
+
+//______________________________________________________________________________
+void  THostAuth::ReOrder(Int_t nmet, Int_t *fmet)
+{
+   // Set new order for existing methods according to fmet
+   int i, j;
+
+   // Book new arrays
+   Int_t   *tMethods = new Int_t[fNumMethods];
+   TString *tDetails = new TString[fNumMethods];
+   Int_t   *flag     = new Int_t[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { flag[i] = 0; }
+
+   // Copy info in the new order
+   int k = 0;
+   for (j = 0; j < nmet; j++) {
+      int jm = -1;
+      for (i = 0; i < fNumMethods; i++) {
+         if (fmet[j] == fMethods[i] && flag[i] == 0) {
+            tMethods[k] = fMethods[i];
+            tDetails[k] = fDetails[i];
+            k++;
+            jm = i;
+            flag[i] = 1;
+         }
+      }
+      if (jm == -1) {
+         Warning("ReOrder","Enter: method %d not among the ones stored - ignore ",fmet[j]);
+      }
+   }
+   // Copying methods not listed ... if any
+   if (k < fNumMethods) {
+      for(i = 0; i < fNumMethods; i++){
+         if (flag[i] == 0) {
+            tMethods[k] = fMethods[i];
+            tDetails[k] = fDetails[i];
+            k++;
+            flag[i] = 1;
+         }
+      }
+   }
+
+   // Resize arrays
+   delete [] fMethods;
+   delete [] fDetails;
+   fMethods = new Int_t[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { fMethods[i] = tMethods[i]; }
+   fDetails = new TString[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { fDetails[i] = tDetails[i]; }
+
+   // delete temporary arrays
+   delete [] tMethods;
+   delete [] tDetails;
+
+   if (gDebug > 3) Print();
+}
+
+//______________________________________________________________________________
+void  THostAuth::SetFirst(Int_t method)
+{
+   // Set 'method' to be the first used (if in the list ...).
+
+   Int_t *meth = new Int_t[1], nmet = 1;
+   meth[0] = method;
+
+   ReOrder(nmet,meth);
+   delete [] meth;
+
+   if (gDebug > 3) Print();
+}
+
+//______________________________________________________________________________
+void THostAuth::SetFirst(Int_t level, char *details)
+{
+   // Set as first method 'level' with authentication 'details'.
+   // Faster then AddMethod(method,details)+SetFirst(method).
+
+   int i;
+
+   // Check first if the method is there already
+   for (i = 0; i < fNumMethods; i++) {
+      if (fMethods[i] == level) {
+         SetDetails(level, details);
+         SetFirst(level);
+         if (gDebug > 1) Print();
+         return;
+      }
+   }
+
+   // If not, added in first position ... Save existing info
+   Int_t   *tMethods = new Int_t[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { tMethods[i] = fMethods[i]; }
+   TString *tDetails = new TString[fNumMethods];
+   for (i = 0; i < fNumMethods; i++) { tDetails[i] = fDetails[i]; }
+
+   // Resize arrays
+   delete [] fMethods;
+   delete [] fDetails;
+   fMethods = new Int_t[fNumMethods+1];
+   fDetails = new TString[fNumMethods+1];
+
+   // This method first
+   fMethods[0] = level;
+   fDetails[0] = details;
+
+   // The others ...
+   for (i = 0; i < fNumMethods; i++) { fMethods[i+1] = tMethods[i]; }
+   for (i = 0; i < fNumMethods; i++) { fDetails[i+1] = tDetails[i]; }
+
+   // delete temporary arrays
+   delete [] tMethods;
+   delete [] tDetails;
+
+   // Increment total number
+   fNumMethods++;
+
+   if (gDebug > 3) Print();
+}
diff --git a/rpdutils/Module.mk b/rpdutils/Module.mk
new file mode 100644
index 0000000000000000000000000000000000000000..7ce78fe89ad798ade614263a5343b8b457789d6d
--- /dev/null
+++ b/rpdutils/Module.mk
@@ -0,0 +1,83 @@
+# Module.mk for Rootd/Proofd authentication utilities
+# Copyright (c) 2002 Rene Brun and Fons Rademakers
+#
+# Author: Gerardo Ganis, 7/4/2003
+
+MODDIR       := rpdutils
+MODDIRS      := $(MODDIR)/src
+MODDIRI      := $(MODDIR)/inc
+
+RPDUTILDIR  := $(MODDIR)
+RPDUTILDIRS := $(RPDUTILDIR)/src
+RPDUTILDIRI := $(RPDUTILDIR)/inc
+
+##### libRPDUtil #####
+RPDUTILH    := $(wildcard $(MODDIRI)/*.h)
+RPDUTILS    := $(wildcard $(MODDIRS)/*.cxx)
+RPDUTILO    := $(RPDUTILS:.cxx=.o)
+
+RPDUTILDEP  := $(RPDUTILO:.o=.d)
+
+##### Flags used in rootd amd proofd Module.mk #####
+# use shadow passwords for authentication
+ifneq ($(SHADOWFLAGS),)
+SHADOWLIBS   := $(SHADOWLIBDIR) $(SHADOWLIB)
+endif
+
+# use AFS for authentication
+ifneq ($(AFSLIB),)
+AFSFLAGS     := -DR__AFS
+AFSLIBS      := $(AFSLIBDIR) $(AFSLIB)
+endif
+
+# use SRP for authentication
+ifneq ($(SRPLIB),)
+SRPFLAGS     := -DR__SRP -I$(SRPINCDIR)
+SRPLIBS      := $(SRPLIBDIR) $(SRPLIB)
+endif
+
+# use krb5 for authentication
+ifneq ($(KRB5LIB),)
+KRB5FLAGS     := -DR__KRB5 -I$(KRB5INCDIR)
+KRB5LIBS      := $(KRB5LIBDIR) $(KRB5LIB)
+endif
+
+# use Globus for authentication
+ifneq ($(GLOBUSLIB),)
+GLBSFLAGS     := -DR__GLBS -I$(GLOBUSINCDIR)
+GLBSLIBS      := $(GLOBUSLIBDIR) $(GLOBUSLIB)
+else
+RPDUTILS      := $(filter-out $(MODDIRS)/globus.cxx,$(RPDUTILS))
+RPDUTILO      := $(filter-out $(MODDIRS)/globus.o,$(RPDUTILO))
+endif
+
+# Combined...
+AUTHFLAGS     := $(SHADOWFLAGS) $(AFSFLAGS) $(SRPFLAGS) $(KRB5FLAGS) \
+                 $(GLBSFLAGS) $(EXTRA_AUTHFLAGS)
+AUTHLIBS      := $(GLBSLIBS) $(SHADOWLIBS) $(AFSLIBS) $(SRPLIBS) $(KRB5LIBS)
+
+# used in the main Makefile
+ALLHDRS     += $(patsubst $(MODDIRI)/%.h,include/%.h,$(RPDUTILH))
+
+# include all dependency files
+INCLUDEFILES += $(RPDUTILDEP)
+
+##### local rules #####
+include/%.h:    $(RPDUTILDIRI)/%.h
+		cp $< $@
+
+all-rpdutils:   $(RPDUTILO)
+
+clean-rpdutils:
+		@rm -f $(RPDUTILO)
+
+clean::         clean-rpdutils
+
+distclean-rpdutils: clean-rpdutils
+		@rm -f $(RPDUTILDEP)
+
+distclean::     distclean-rpdutils
+
+##### extra rules ######
+$(RPDUTILO): %.o: %.cxx
+	$(CXX) $(OPT) $(CXXFLAGS) $(AUTHFLAGS) -o $@ -c $<
diff --git a/rpdutils/inc/rpderr.h b/rpdutils/inc/rpderr.h
new file mode 100644
index 0000000000000000000000000000000000000000..51501cdf15c68168740537a3bbd8dcca6e4292cc
--- /dev/null
+++ b/rpdutils/inc/rpderr.h
@@ -0,0 +1,31 @@
+// @(#)root/rpdutils:$Name:  $:$Id: rootd.h,v 1.2 2001/02/22 09:43:25 rdm Exp $
+// Author: Fons Rademakers   11/08/97
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_rpderr
+#define ROOT_rpderr
+
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// rpderr                                                               //
+//                                                                      //
+// This header file defines error codes generated by rootd/proofd.      //
+// NB: In case of change update also strings in net/inc/ErrStr.h        //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef ROOT_NetErrors
+#include "NetErrors.h"
+#endif
+
+typedef void (*ErrorHandler_t)(int level, const char *msg);
+
+#endif
diff --git a/rpdutils/inc/rpdp.h b/rpdutils/inc/rpdp.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb1860158cb968f0d49a235765d39c06bd38d511
--- /dev/null
+++ b/rpdutils/inc/rpdp.h
@@ -0,0 +1,207 @@
+// @(#)root/rpdutils:$Name:  $:$Id: rootd.h,v 1.2 2001/02/22 09:43:25 rdm Exp $
+// Author: Gerardo Ganis   7/4/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_rpdp
+#define ROOT_rpdp
+
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// rpdp                                                                 //
+//                                                                      //
+// This header file contains private definitions and declarations       //
+// used by modules in rpdutils/src.                                     //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef ROOT_VarArgs
+#include "Varargs.h"
+#endif
+#ifndef ROOT_MessageTypes
+#include "MessageTypes.h"
+#endif
+#ifndef ROOT_rpderr
+#include "rpderr.h"
+#endif
+
+typedef void (*SigPipe_t)(int);
+
+// Global consts
+const int  kMAXSEC           = 6;
+const int  kMAXSECBUF        = 2048;
+const int  kAUTH_REUSE_MSK   = 0x1;
+const int  kAUTH_CRYPT_MSK   = 0x2;
+const int  kMAXPATHLEN       = 1024;
+
+// type of authentication method
+enum  ESecurity { kClear, kSRP, kKrb5, kGlobus, kSSH, kRfio };
+
+// type of service
+enum  EService  { kROOTD = 1, kPROOFD };
+
+// Extern globals
+namespace ROOT {
+
+extern int  gAltSRP;
+extern int  gAnon;
+extern int  gAuth;
+extern int  gClientProtocol;
+extern int  gGlobus;
+extern int  gNumAllow;
+extern int  gNumLeft;
+extern int  gOffSet;
+extern int  gParallel;
+extern int  gRemPid;
+extern int  gReUseAllow;
+extern int  gReUseRequired;
+extern int  gSockFd;
+extern int  gSshdPort;
+
+extern char gAltSRPPass[kMAXPATHLEN];
+extern char gAnonUser[64];
+extern char gAuthAllow[kMAXPATHLEN];
+extern char gExecDir[kMAXPATHLEN];        // for use in rootd ...
+extern char gFile[kMAXPATHLEN];
+extern char gFileLog[kMAXPATHLEN];
+extern char gHostCertConf[kMAXPATHLEN];   // Defines certificate location for globus authentication
+extern char gOpenHost[256];
+extern char gService[10];                 // "rootd" or "proofd", defined in proofd/rootd.cxx ...
+extern char gTmpDir[kMAXPATHLEN];         // directory for temporary files (RW)
+
+extern char gUser[64];
+extern char gPasswd[64];                     // only used for anonymous access
+
+extern SigPipe_t gSigPipeHook;
+
+extern double gBytesSent;
+extern double gBytesRecv;
+
+// Error handlers prototypes ...
+extern ErrorHandler_t gErrSys;
+extern ErrorHandler_t gErrFatal;
+extern ErrorHandler_t gErr;
+
+} // namespace ROOT
+
+
+namespace ROOT {
+
+// error.cxx
+int  GetErrno();
+void ResetErrno();
+void ErrorInit(const char *ident);
+void ErrorInfo(const char *va_(fmt), ...);
+void Perror(char *buf);
+void Error(ErrorHandler_t ErrHand,int code,const char *va_(fmt), ...);
+
+// net.cxx
+int NetSendRaw(const void *buf, int len);
+int NetRecvRaw(void *buf, int len);
+int NetRecvRaw(int sock, void *buf, int len);
+int NetSend(const void *buf, int len, EMessageTypes kind);
+int NetSend(int code, EMessageTypes kind);
+int NetSend(const char *msg, EMessageTypes kind = kMESS_STRING);
+int NetSendAck();
+int NetSendError(ERootdErrors err);
+int NetRecv(void *&buf, int &len, EMessageTypes &kind);
+int NetRecv(char *msg, int len, EMessageTypes &kind);
+int NetRecv(char *msg, int max);
+int NetOpen(int inetdflag, EService service);
+void NetClose();
+const char *NetRemoteHost();
+int  NetInit(const char *service, int port1, int port2, int tcpwindowsize);
+void NetInit(const char *service, int port, int tcpwindowsize);
+void NetSetOptions(EService service, int sock, int tcpwindowsize);
+
+// netpar.cxx
+int  NetParOpen(int port, int size);
+void NetParClose();
+int  NetParSend(const void *buf, int len);
+int  NetParRecv(void *buf, int len);
+
+// daemon.cxx
+void DaemonStart(int ignsigcld, int fdkeep, EService service);
+
+// rpdutils.cxx
+int  RpdGetAuthMethod(int kind);
+int  RpdUpdateAuthTab(int opt, char *line, char **token);
+int  RpdCleanupAuthTab(char *Host, int RemId);
+int  RpdCheckAuthTab(int Sec, char *User, char *Host,int RemId, int *OffSet);
+bool RpdReUseAuth(const char *sstr, int kind);
+int  RpdCheckAuthAllow(int Sec, char *Host);
+int  RpdCheckHostWild(const char *Host, const char *host);
+char *RpdGetIP(const char *host);
+void RpdSendAuthList();
+void RpdCheckSession(int period);
+
+void RpdUser(const char *sstr);
+void RpdSshAuth(const char *sstr);
+void RpdKrb5Auth(const char *sstr);
+void RpdSRPUser(const char *user);
+int  RpdCheckSpecialPass(const char *passwd);
+void RpdPass(const char *pass);
+void RpdGlobusAuth(const char *sstr);
+void RpdRfioAuth(const char *sstr);
+void RpdCleanup(const char *sstr);
+
+void RpdDefaultAuthAllow();
+int  RpdCheckDaemon(const char *daemon);
+int  RpdCheckSshd();
+int  RpdGuessClientProt(const char *buf, EMessageTypes kind);
+char *RpdGetRandString(int Opt, int Len);
+bool RpdCheckToken(char *tknin, char *tknref);
+
+void RpdSetAuthTabFile(char *AuthTabFile);
+void RpdSetDebugFlag(int Debug);
+void RpdSetRootLogFlag(int RootLog);
+
+int  RpdGetRSAKeys(char *PubKey, int Opt);
+void RpdSavePubKey(char *PubKey, int OffSet);
+int  RpdSecureSend(char *Str);
+int  RpdSecureRecv(char **Str);
+
+
+} // namespace ROOT
+
+// Globus stuff ...
+#ifdef R__GLBS
+extern "C" {
+   #include <globus_gss_assist.h>
+   #include <openssl/x509.h>
+   #include <openssl/pem.h>
+   #include <sys/ipc.h>
+   #include <sys/shm.h>
+}
+// Globus Utility Function prototypes ...
+namespace ROOT {
+
+void  GlbsToolError(char *, int, int, int);
+int   GlbsToolCheckCert(char *, char **);
+int   GlbsToolCheckContext(int);
+int   GlbsToolStoreContext(gss_ctx_id_t, char *);
+int   GlbsToolStoreToShm(gss_buffer_t, int *);
+char *GlbsToolExpand(char *);
+
+} // namespace ROOT
+
+#endif  // Globus ...
+
+namespace ROOT {
+
+// Ssh Utility Function prototypes ...
+int   SshToolAllocateSocket(unsigned int, unsigned int, char **);
+void  SshToolDiscardSocket(char *, int);
+int   SshToolNotifyFailure(char *);
+int   SshToolGetAuth(int);
+
+} // namespace ROOT
+
+#endif
diff --git a/rpdutils/src/daemon.cxx b/rpdutils/src/daemon.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..79abfeac15e3ac5c593efb3f24032ea532acc012
--- /dev/null
+++ b/rpdutils/src/daemon.cxx
@@ -0,0 +1,218 @@
+// @(#)root/rpdutils:$Name:  $:$Id: daemon.cxx,v 1.5 2002/10/28 14:22:51 rdm Exp $
+// Author: Fons Rademakers   11/08/97
+// Modifified: Gerardo Ganis 8/04/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// DaemonStart                                                          //
+//                                                                      //
+// Detach a daemon process from login session context.                  //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#if defined(__sun) || defined(__sgi)
+#  include <fcntl.h>
+#endif
+
+#ifdef SIGTSTP
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#endif
+
+#ifndef NOFILE
+#   define NOFILE 0
+#endif
+
+#if defined(__hpux)
+#define USE_SIGCHLD
+#endif
+
+#if defined(__FreeBSD__) || defined(__APPLE__)
+#define USE_SIGCHLD
+#define	SIGCLD SIGCHLD
+#endif
+
+#if defined(linux) || defined(__hpux) || defined(__sun) || defined(__sgi) || \
+    defined(_AIX) || defined(__FreeBSD__) || defined(__APPLE__) || \
+    defined(__MACH__)  || (defined(__CYGWIN__) && defined(__GNUC__))
+#define USE_SETSID
+#endif
+
+
+#include "rpdp.h"
+
+namespace ROOT {
+
+extern int     gDebug;
+
+#if defined(USE_SIGCHLD)
+//______________________________________________________________________________
+static void SigChild(int)
+{
+   int         pid;
+#if defined(__hpux) || defined(__FreeBSD__) || defined(__APPLE__)
+   int status;
+#else
+   union wait  status;
+#endif
+
+   while ((pid = wait3(&status, WNOHANG, 0)) > 0)
+      ;
+}
+#endif
+
+//______________________________________________________________________________
+void DaemonStart(int ignsigcld, int fdkeep, EService service)
+{
+   // Detach a daemon process from login session context.
+
+   // If we were started by init (process 1) from the /etc/inittab file
+   // there's no need to detach.
+   // This test is unreliable due to an unavoidable ambiguity
+   // if the process is started by some other process and orphaned
+   // (i.e. if the parent process terminates before we are started).
+
+   int fd;
+
+#if !(defined(__CYGWIN__) && defined(__GNUC__))
+   if (getppid() == 1) {
+      if (service == kROOTD) printf ("ROOTD_PID=%ld\n", (long) getpid());
+      goto out;
+   }
+#endif
+
+   // Ignore the terminal stop signals (BSD).
+
+#ifdef SIGTTOU
+   signal(SIGTTOU, SIG_IGN);
+#endif
+#ifdef SIGTTIN
+   signal(SIGTTIN, SIG_IGN);
+#endif
+#ifdef SIGTSTP
+   signal(SIGTSTP, SIG_IGN);
+#endif
+
+   // If we were not started in the background, fork and let the parent
+   // exit. This also guarantees the first child is not a process
+   // group leader.
+
+   int childpid;
+   if ((childpid = fork()) < 0) {
+      if (service == kROOTD) fprintf(stderr, "DaemonStart: can't fork first child\n");
+      Error(gErrSys,kErrFatal, "DaemonStart: can't fork first child");
+   } else if (childpid > 0) {
+#ifdef SIGTSTP
+      if (service == kROOTD) printf("ROOTD_PID=%d\n", childpid);
+#endif
+      exit(0);    // parent
+   } else {
+      if (gDebug > 3)
+         ErrorInfo("DaemonStart: this is the child thread ... socket is: %d",fdkeep);
+   }
+
+   // First child process...
+
+   // Disassociate from controlling terminal and process group.
+   // Ensure the process can't reacquire a new controlling terminal.
+
+#ifdef SIGTSTP
+
+#ifdef USE_SETSID
+   if (setsid() == -1) {
+#else
+   if (setpgrp(0, getpid()) == -1) {
+#endif
+      if (service == kROOTD) fprintf(stderr, "DaemonStart: can't change process group\n");
+      Error(gErrSys,kErrFatal, "DaemonStart: can't change process group");
+   }
+
+   if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
+#if !defined(__hpux) && !defined(__sun) && \
+    !(defined(__CYGWIN__) && defined(__GNUC__))
+      ioctl(fd, TIOCNOTTY, 0);       // loose controlling tty
+#endif
+      close(fd);
+   }
+
+#else
+
+   if (setpgrp() == -1) {
+      if (service == kROOTD) fprintf(stderr,     "DaemonStart: can't change process group\n");
+      Error(gErrSys,kErrFatal, "DaemonStart: can't change process group");
+   }
+
+
+   signal(SIGHUP, SIG_IGN);    // immune from pgrp leader death
+
+   if ((childpid = fork()) < 0) {
+      if (service == kROOTD) fprintf(stderr,     "DaemonStart: can't fork second child\n");
+      Error(gErrSys,kErrFatal, "DaemonStart: can't fork second child");
+   } else if (childpid > 0) {
+      if (service == kROOTD) printf("ROOTD_PID=%d\n", childpid);
+      exit(0);    // first child
+   }
+
+#endif
+out:
+   // Close any open file descriptors
+   for (fd = 0; fd < NOFILE; fd++) {
+      int rc=-10;
+      if ((fd != fdkeep) || (service == kPROOFD)) rc = close(fd);
+      //if (rc==-1) ErrorInfo("DaemonStart: error closing file descriptor (rc=%d) %d: errno: %d ",rc,fd,(int)errno);
+   }
+
+   ResetErrno();   // probably got set to EBADF from a close
+
+   // Move current directory to root, make sure we aren't on a mounted
+   // file system.
+
+   chdir("/");
+
+   // Clear any inherited file mode creation mask
+
+   umask(0);
+
+   // See if the caller isn't interested in the exit status of its
+   // children and doesn't want to have them become zombies and
+   // clog up the system.
+   // With SysV all we need to do is ignore the signal.
+   // With BSD, however, we have to catch each signal
+   // and execute the wait3() system call.
+
+   if (ignsigcld) {
+#ifdef USE_SIGCHLD
+      signal(SIGCLD, SigChild);
+#else
+#if defined(__alpha) && !defined(linux)
+      struct sigaction oldsigact, sigact;
+      sigact.sa_handler = SIG_IGN;
+      sigemptyset(&sigact.sa_mask);
+      sigact.sa_flags = SA_NOCLDWAIT;
+      sigaction(SIGCHLD, &sigact, &oldsigact);
+#elif defined(__sun)
+      sigignore(SIGCHLD);
+#else
+      signal(SIGCLD, SIG_IGN);
+#endif
+#endif
+   }
+}
+
+} // namespace ROOT
+
diff --git a/rpdutils/src/error.cxx b/rpdutils/src/error.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..376d8c7707ce366c2c67375975eae50fca16f3fc
--- /dev/null
+++ b/rpdutils/src/error.cxx
@@ -0,0 +1,153 @@
+// @(#)root/rpdutils:$Name:  $:$Id: daemon.cxx,v 1.5 2002/10/28 14:22:51 rdm Exp $
+// Author: Fons Rademakers   11/08/97
+// Modifified: Gerardo Ganis 8/04/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// error                                                                //
+//                                                                      //
+// Set of error handling routines for daemon process.                   //
+// Merging of rootd and proofd/src/error.cxx                            //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+
+#if defined(hpux9)
+extern "C" {
+   extern void openlog(const char *, int, int);
+   extern void syslog(int, const char *, ...);
+}
+#endif
+
+#ifdef __sun
+#   ifndef _REENTRANT
+#      if __SUNPRO_CC > 0x420
+#         define GLOBAL_ERRNO
+#      endif
+#   endif
+#endif
+
+#include "rpderr.h"
+#include "rpdp.h"
+
+namespace ROOT {
+
+extern int     gDebug;
+extern int     gRootLog;
+
+ErrorHandler_t gErrSys   = 0;
+ErrorHandler_t gErrFatal = 0;
+ErrorHandler_t gErr      = 0;
+
+
+//______________________________________________________________________________
+int GetErrno()
+{
+#ifdef GLOBAL_ERRNO
+   return ::errno;
+#else
+   return errno;
+#endif
+}
+
+//______________________________________________________________________________
+void ResetErrno()
+{
+#ifdef GLOBAL_ERRNO
+   ::errno = 0;
+#else
+   errno = 0;
+#endif
+}
+
+//______________________________________________________________________________
+void ErrorInfo(const char *va_(fmt), ...)
+{
+   // Write info message to syslog.
+
+   char    buf[1024];
+   va_list ap;
+
+   va_start(ap,va_(fmt));
+   vsprintf(buf, fmt, ap);
+   va_end(ap);
+
+   if (gRootLog == 0) {
+    syslog(LOG_INFO, buf);
+   } else if (gRootLog == 1) {
+     fprintf(stderr, "%s\n",buf);
+   } else if (gRootLog == 2) {
+     if (strlen(gFileLog)>0) {
+       FILE *fl= fopen(gFileLog,"a");
+       fprintf(fl, "%s\n",buf);
+       fclose(fl);
+     }
+   }
+}
+
+//______________________________________________________________________________
+void ErrorInit(const char *ident)
+{
+   // Open syslog.
+
+   openlog(ident, (LOG_PID | LOG_CONS), LOG_DAEMON);
+}
+
+//______________________________________________________________________________
+void Perror(char *buf)
+{
+   // Return in buf the message belonging to errno.
+
+   int len = strlen(buf);
+#if (defined(__sun) && defined (__SVR4)) || defined (__linux) || \
+   defined(_AIX) || defined(__MACH__)
+   sprintf(buf+len, " (%s)", strerror(GetErrno()));
+#else
+   if (GetErrno() >= 0 && GetErrno() < sys_nerr)
+      sprintf(buf+len, " (%s)", sys_errlist[GetErrno()]);
+#endif
+}
+
+//______________________________________________________________________________
+void Error(ErrorHandler_t func, int code, const char *va_(fmt), ...)
+{
+   // Write fatal message to syslog and exit.
+
+   char    buf[1024];
+   va_list ap;
+
+   va_start(ap,va_(fmt));
+   vsprintf(buf, fmt, ap);
+   va_end(ap);
+
+   if (gRootLog == 0) {
+      syslog(LOG_ERR, buf);
+   } else if (gRootLog == 1) {
+      fprintf(stderr, "%s\n",buf);
+   } else if (gRootLog == 2) {
+      if (strlen(gFileLog)>0) {
+         FILE *fl= fopen(gFileLog,"a");
+         fprintf(fl, "%s\n",buf);
+         fclose(fl);
+      }
+   }
+
+   // Actions are defined by the specific error handler (see rootd.cxx and proofd.cxx)
+   if (func) (*func)(code,(const char *)buf);
+}
+
+} // namespace ROOT
diff --git a/rpdutils/src/globus.cxx b/rpdutils/src/globus.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c40e1ba4002557249a847fc301b417367d7a34ef
--- /dev/null
+++ b/rpdutils/src/globus.cxx
@@ -0,0 +1,566 @@
+// @(#)root/rpdutils:$Name:  $:$Id: daemon.cxx,v 1.5 2002/10/28 14:22:51 rdm Exp $
+// Author: Gerardo Ganis    7/4/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// globus                                                               //
+//                                                                      //
+// Set of utilities for rootd/proofd daemon authentication via Globus   //
+// certificates.                                                        //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "rpdp.h"
+
+
+
+namespace ROOT {
+
+extern int gDebug;
+
+//--- Globals ------------------------------------------------------------------
+char gHostCertConf[kMAXPATHLEN] = "/etc/root/hostcert.conf"; // Defines certificate location for globus authentication
+
+//______________________________________________________________________________
+void GlbsToolError(char *mess, int majs, int mins, int toks)
+{
+   // Handle error ...
+
+   char *GlbErr;
+
+   if (!globus_gss_assist_display_status_str
+      (&GlbErr, mess, majs, mins, toks)) {
+   } else {
+      GlbErr = new char[kMAXPATHLEN];
+      sprintf(GlbErr, "%s: error messaged not resolved ", mess);
+   }
+   NetSend(kErrFatal, kROOTD_ERR);
+   ErrorInfo("Error: %s (majst=%d,minst=%d,tokst:%d)", GlbErr, majs, mins,
+             toks);
+
+   delete [] GlbErr;
+}
+
+//_________________________________________________________________________
+int GlbsToolCheckCert(char *ClientIssuerName, char **SubjName)
+{
+   // Load information about available certificates from user specified
+   // sources or from defaults.
+   // Returns number of potentially valid dir/cert/key triplets found.
+
+   int retval = 1;
+   //   char             *hostcertconf_default  = "globusauth/etc/hostcert.conf";
+   //   char             *hostcertconf          = 0;
+   char *certdir_default  = "/etc/grid-security/certificates";
+   char *hostcert_default = "/etc/grid-security/hostcert.pem";
+   char *hostkey_default  = "/etc/grid-security/hostkey.pem";
+   char *gridmap_default  = "/etc/grid-security/grid-mapfile";
+   char dir_def[kMAXPATHLEN] = { 0 }, cert_def[kMAXPATHLEN] = { 0 },
+        key_def[kMAXPATHLEN] = { 0 }, map_def[kMAXPATHLEN]  = { 0 };
+   char *dir_tmp = 0, *cert_tmp = 0, *key_tmp = 0, *map_tmp = 0;
+   bool CertFound = 0;
+   X509 *xcert = 0;
+   FILE *fcert = 0;
+   char *issuer_name = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("GlbsToolCheckCert: enter: %s", ClientIssuerName);
+
+   if (gHostCertConf != 0) {
+      // The user/administrator provided a file ... check if it exists and can be read
+      FILE *fconf = 0;
+      if (!access(gHostCertConf, F_OK) && !access(gHostCertConf, R_OK) &&
+          (fconf = fopen(gHostCertConf, "r")) != 0) {
+         char line[kMAXPATHLEN];
+         if (gDebug > 2)
+            ErrorInfo("GlbsToolLoadCertInfo: reading host cert file %s",
+                      gHostCertConf);
+
+         // ... let's see what it's inside
+         while (fgets(line, sizeof(line), fconf)) {
+            if (line[0] == '#')
+               continue;        // skip comment lines
+            int nw =
+                sscanf(line, "%s %s %s %s", dir_def, cert_def, key_def,
+                       map_def);
+
+            // allow for imcomplete lines ... completion with defaults ...
+            if (nw == 1) {
+               strcpy(cert_def, hostcert_default);
+               strcpy(key_def, hostkey_default);
+               strcpy(map_def, gridmap_default);
+            } else if (nw == 2) {
+               strcpy(key_def, hostkey_default);
+               strcpy(map_def, gridmap_default);
+            } else if (nw == 3) {
+               strcpy(map_def, gridmap_default);
+            }
+            // Expand for test if needed
+            dir_tmp  = GlbsToolExpand(dir_def);
+            cert_tmp = GlbsToolExpand(cert_def);
+            key_tmp  = GlbsToolExpand(key_def);
+            map_tmp  = GlbsToolExpand(map_def);
+            if (gDebug > 2)
+               ErrorInfo
+                   ("GlbsToolLoadCertInfo: testing host cert file map %s %s %s %s",
+                    dir_tmp, cert_tmp, key_tmp, map_tmp);
+
+            // check that the files exist and can be read
+            if (!access(dir_tmp, F_OK) && !access(dir_tmp, R_OK)) {
+               if (!access(cert_tmp, F_OK) && !access(cert_tmp, R_OK)) {
+                  if (!access(key_tmp, F_OK) && !access(key_tmp, R_OK)) {
+                     /// Load certificate
+                     fcert = fopen(cert_tmp, "r");
+                     if (!PEM_read_X509(fcert, &xcert, 0, 0)) {
+                        ErrorInfo
+                            ("GlbsToolCheckCert: unable to load host certificate (%s)",
+                             cert_tmp);
+                        goto goout;;
+                     }
+                     // Get the issuer name
+                     issuer_name =
+                         X509_NAME_oneline(X509_get_issuer_name(xcert), 0,
+                                           0);
+                     if (strstr(issuer_name, ClientIssuerName) != 0) {
+                        CertFound = 1;
+                        if (gDebug > 2)
+                           ErrorInfo
+                               ("GlbsToolCheckCert: Issuer Subject: %s matches",
+                                issuer_name);
+                        fclose(fconf);
+                        goto found;
+                     }
+                  } else {
+                     if (gDebug > 2)
+                        ErrorInfo
+                            ("GlbsToolCheckCert: key file not existing or not readable (%s)",
+                             key_tmp);
+                  }
+               } else {
+                  if (gDebug > 2)
+                     ErrorInfo
+                         ("GlbsToolCheckCert: cert file not existing or not readable (%s)",
+                          cert_tmp);
+               }
+            } else {
+               if (gDebug > 2)
+                  ErrorInfo
+                      ("GlbsToolCheckCert: cert directory not existing or not readable (%s)",
+                       dir_tmp);
+            }
+            if (gDebug > 2)
+               ErrorInfo
+                   ("GlbsToolCheckCert: read cert key map files: %s %s %s %s",
+                    dir_tmp, cert_tmp, key_tmp, map_tmp);
+         }
+         fclose(fconf);
+
+      } else {
+         if (gDebug > 2)
+            ErrorInfo
+                ("GlbsToolLoadCertInfo: host cert conf not existing or not readable (%s)",
+                 gHostCertConf);
+      }
+   } else if (gDebug > 2)
+      ErrorInfo("GlbsToolCheckCert: HOSTCERTCONF undefined");
+   if (gDebug > 2)
+      ErrorInfo
+          ("GlbsToolCheckCert: Try to use env definitions or defaults ...");
+
+   // We have not found a goof one: try with these envs definitions or the defaults ...
+   if (getenv("X509_CERT_DIR") != 0) {
+      strcpy(dir_def, getenv("X509_CERT_DIR"));
+   } else
+      strcpy(dir_def, certdir_default);
+   if (getenv("X509_USER_CERT") != 0) {
+      strcpy(cert_def, getenv("X509_USER_CERT"));
+   } else
+      strcpy(cert_def, hostcert_default);
+   if (getenv("X509_USER_KEY") != 0) {
+      strcpy(key_def, getenv("X509_USER_KEY"));
+   } else
+      strcpy(key_def, hostkey_default);
+   if (getenv("GRIDMAP") != 0) {
+      strcpy(map_def, getenv("GRIDMAP"));
+   } else
+      strcpy(map_def, gridmap_default);
+
+   // Expand for test if needed
+   dir_tmp  = GlbsToolExpand(dir_def);
+   cert_tmp = GlbsToolExpand(cert_def);
+   key_tmp  = GlbsToolExpand(key_def);
+   map_tmp  = GlbsToolExpand(map_def);
+
+   if (!access(dir_tmp, F_OK) && !access(dir_tmp, R_OK)) {
+      if (!access(cert_tmp, F_OK) && !access(cert_tmp, R_OK)) {
+         if (!access(key_tmp, F_OK) && !access(key_tmp, R_OK)) {
+            // Load certificate
+            fcert = fopen(cert_tmp, "r");
+            if (!PEM_read_X509(fcert, &xcert, 0, 0)) {
+               ErrorInfo
+                   ("GlbsToolCheckCert: unable to load host certificate (%s)",
+                    cert_tmp);
+               goto goout;
+            }
+            // Get the issuer name
+            issuer_name =
+                X509_NAME_oneline(X509_get_issuer_name(xcert), 0, 0);
+            if (strstr(issuer_name, ClientIssuerName) != 0) {
+               CertFound = 1;
+               if (gDebug > 2)
+                  ErrorInfo
+                      ("GlbsToolCheckCert: Issuer Subject: %s matches",
+                       issuer_name);
+               goto found;
+            }
+         } else {
+            ErrorInfo
+                ("GlbsToolCheckCert: default hostkey file not existing or not readable (%s)",
+                 key_tmp);
+            goto goout;
+         }
+      } else {
+         ErrorInfo
+             ("GlbsToolCheckCert: default hostcert file not existing or not readable (%s)",
+              cert_tmp);
+         goto goout;
+      }
+   } else {
+      ErrorInfo
+          ("GlbsToolCheckCert: default cert dirrectory not existing or not readable (%s)",
+           dir_tmp);
+      goto goout;
+   }
+
+ goout:
+   if (dir_tmp)
+      delete[]dir_tmp;
+   if (cert_tmp)
+      delete[]cert_tmp;
+   if (key_tmp)
+      delete[]key_tmp;
+   if (map_tmp)
+      delete[]map_tmp;
+   return 1;
+
+ found:
+   if (CertFound) {
+      // Get the subject name
+      char *subject_name =
+          X509_NAME_oneline(X509_get_subject_name(xcert), 0, 0);
+      if (gDebug > 2) {
+         ErrorInfo("GlbsToolCheckCert: issuer: %s", issuer_name);
+         ErrorInfo("GlbsToolCheckCert: subject: %s", subject_name);
+      }
+      // Send it to the client ...
+      *SubjName = strdup(subject_name);
+      // Mission ok ..
+      retval = 0;
+      // free resources
+      free(issuer_name);
+      free(subject_name);
+      // We have found a valid one ...
+      fclose(fcert);
+
+      // We set the relevant environment variables ...
+      if (setenv("X509_CERT_DIR", dir_def, 1)) {
+         ErrorInfo("GlbsToolCheckCert: unable to set X509_CERT_DIR ");
+         return 1;
+      }
+      if (setenv("X509_USER_CERT", cert_def, 1)) {
+         ErrorInfo("GlbsToolCheckCert: unable to set X509_USER_CERT ");
+         return 1;
+      }
+      if (setenv("X509_USER_KEY", key_def, 1)) {
+         ErrorInfo("GlbsToolCheckCert: unable to set X509_USER_KEY ");
+         return 1;
+      }
+      if (setenv("GRIDMAP", map_def, 1)) {
+         ErrorInfo("GlbsToolCheckCert: unable to set GRIDMAP ");
+      }
+   }
+   return retval;
+}
+
+
+//______________________________________________________________________________
+int GlbsToolCheckContext(int ShmId)
+{
+   // Checks validity of security context exported in shared memory
+   // segment SHmId. Returns 1 if valid, 0 othrwise.
+
+   int retval = 0;
+   OM_uint32 MajStat = 0;
+   OM_uint32 MinStat = 0;
+   gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
+   OM_uint32 GssRetFlags = 0;
+   OM_uint32 GlbContLifeTime = 0;
+   int Dum1, Dum2;
+   gss_OID MechType;
+   gss_name_t *TargName = 0, *Name = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("GlbsToolCheckContext: checking contetx in shm : %d",
+                ShmId);
+
+   // retrieve the context from shared memory ...
+   gss_buffer_t databuf = (gss_buffer_t) shmat(ShmId, 0, 0);
+   if (gDebug > 2)
+      ErrorInfo
+          ("GlbsToolCheckContext: retrieving info from shared memory: %d",
+           ShmId);
+
+   // Import the security context ...
+   gss_buffer_t SecContExp =
+       (gss_buffer_t) new char[sizeof(gss_buffer_desc) + databuf->length];
+   SecContExp->length = databuf->length;
+   SecContExp->value =
+       (void *) ((char *) SecContExp + sizeof(size_t) + sizeof(void *));
+   void *dbufval =
+       (void *) ((char *) databuf + sizeof(size_t) + sizeof(void *));
+   memmove(SecContExp->value, dbufval, SecContExp->length);
+   if ((MajStat =
+        gss_import_sec_context(&MinStat, SecContExp,
+                               &context_handle)) != GSS_S_COMPLETE) {
+      GlbsToolError("GlbsToolCheckContext: gss_import_sec_context",
+                    MajStat, MinStat, 0);
+   } else if (gDebug > 2)
+      ErrorInfo
+          ("GlbsToolCheckContext: GlbsTool Sec Context successfully imported (0x%x)",
+           context_handle);
+
+   delete[]SecContExp;
+
+   // Detach from shared memory segment
+   int rc = shmdt((const void *) databuf);
+   if (rc != 0) {
+      ErrorInfo
+          ("GlbsToolCheckContext: unable to detach from shared memory segment %d (rc=%d)",
+           ShmId, rc);
+   }
+   // Check validity of the retrieved context ...
+   if (context_handle != 0 && context_handle != GSS_C_NO_CONTEXT) {
+      if ((MajStat =
+           gss_inquire_context(&MinStat, context_handle, Name, TargName,
+                               &GlbContLifeTime, &MechType, &GssRetFlags,
+                               &Dum1, &Dum2)) != GSS_S_COMPLETE) {
+         GlbsToolError("GlbsToolCheckContext: gss_inquire_context",
+                       MajStat, MinStat, 0);
+         // mark segment for distruction
+         struct shmid_ds shm_ds;
+         if (!shmctl(ShmId, IPC_RMID, &shm_ds))
+            ErrorInfo
+                ("GlbsToolCheckContext: unable to mark shared memory segment %d for desctruction",
+                 ShmId);
+      } else {
+         if (gDebug > 2)
+            ErrorInfo
+                ("GlbsToolCheckContext: found valid context in shm %d",
+                 ShmId);
+         retval = 1;
+      }
+   }
+
+   return retval;
+}
+
+//______________________________________________________________________________
+int GlbsToolStoreContext(gss_ctx_id_t context_handle, char *user)
+{
+   // Exports a security context for later use and stores in a shared memory
+   // segments. On success returns Id of the allocated shared memory segment,
+   // 0 otherwise.
+
+   OM_uint32 MajStat;
+   OM_uint32 MinStat;
+   key_t shm_key = IPC_PRIVATE;
+   int shm_flg = 0777;
+   struct shmid_ds shm_ds;
+
+   if (gDebug > 2)
+      ErrorInfo("GlbsToolStoreContext: Enter");
+
+   // First we have to prepare the export of the security context
+   gss_buffer_t SecContExp = new gss_buffer_desc;
+   if ((MajStat =
+        gss_export_sec_context(&MinStat, &context_handle,
+                               SecContExp)) != GSS_S_COMPLETE) {
+      GlbsToolError("GlbsToolStoreContext: gss_export_sec_context",
+                    MajStat, MinStat, 0);
+      delete SecContExp;
+      return 0;
+   } else if (gDebug > 2)
+      ErrorInfo
+          ("GlbsToolStoreContext: security context prepared for export");
+
+   // This is the size of the needed shared memory segment
+   int shm_size = sizeof(gss_buffer_desc) + SecContExp->length;
+   if (gDebug > 2)
+      ErrorInfo
+          ("GlbsToolStoreContext: needed shared memory segment sizes: %d",
+           shm_size);
+
+   // Here we allocate the shared memory segment
+   int ShmId = shmget(shm_key, shm_size, shm_flg);
+   if (ShmId < 0) {
+      ErrorInfo
+          ("GlbsToolStoreContext: while allocating shared memory segment (rc=%d)",
+           ShmId);
+      delete SecContExp;
+      return 0;
+   } else if (gDebug > 2)
+      ErrorInfo
+          ("GlbsToolStoreContext: shared memory segment allocated (id=%d)",
+           ShmId);
+
+   // Attach segment to address
+   gss_buffer_t databuf = (gss_buffer_t) shmat(ShmId, 0, 0);
+   if ((int) databuf < 0) {
+      ErrorInfo
+          ("GlbsToolStoreContext: while attaching to shared memory segment (rc=%d)",
+           (int) databuf);
+      delete SecContExp;
+      return 0;
+   }
+   databuf->length = SecContExp->length;
+   databuf->value =
+       (void *) ((char *) databuf + sizeof(size_t) + sizeof(void *));
+   memmove(databuf->value, SecContExp->value, SecContExp->length);
+
+   // Now we can detach from the shared memory segment ... and release memory we don't anylonger
+   int rc = 0;
+   if ((rc = shmdt((const void *) databuf)) != 0) {
+      ErrorInfo
+          ("GlbsToolStoreContext: unable to detach from shared memory segment (rc=%d)",
+           rc);
+   }
+   delete SecContExp;
+
+   // We need to change the ownership of the shared memory segment used
+   // for credential export to allow proofserv to destroy it
+   if (shmctl(ShmId, IPC_STAT, &shm_ds) == -1) {
+      ErrorInfo
+          ("GlbsToolStoreContext: can't get info about shared memory segment %d",
+           ShmId);
+      return 0;
+   }
+   // Get info about user logging in
+   struct passwd *pw = getpwnam(user);
+
+   // Give use ownership of the shared memory segment ...
+   shm_ds.shm_perm.uid = pw->pw_uid;
+   shm_ds.shm_perm.gid = pw->pw_gid;
+   if (shmctl(ShmId, IPC_SET, &shm_ds) == -1) {
+      ErrorInfo
+          ("GlbsToolStoreContext: can't change ownership of shared memory segment %d",
+           ShmId);
+      return 0;
+   }
+   // return shmid to rootd
+   return ShmId;
+}
+
+//______________________________________________________________________________
+int GlbsToolStoreToShm(gss_buffer_t buffer, int *ShmId)
+{
+   // Creates a shm and stores buffer in it.
+   // Returns 0 on success (shm id in ShmId), >0 otherwise.
+
+   key_t shm_key = IPC_PRIVATE;
+   int shm_flg = 0777;
+
+   if (gDebug > 2)
+      ErrorInfo("GlbsToolStoreToShm: Enter: ShmId: %d", ShmId);
+
+   // This is the size of the needed shared memory segment
+   int shm_size = sizeof(gss_buffer_desc) + buffer->length;
+   if (gDebug > 2)
+      ErrorInfo
+          ("GlbsToolStoreToShm: needed shared memory segment sizes: %d",
+           shm_size);
+
+   // Here we allocate the shared memory segment
+   int lShmId = shmget(shm_key, shm_size, shm_flg);
+   if (lShmId < 0) {
+      ErrorInfo
+          ("GlbsToolStoreToShm: while allocating shared memory segment (rc=%d)",
+           lShmId);
+      return 1;
+   } else if (gDebug > 2)
+      ErrorInfo
+          ("GlbsToolStoreToShm: shared memory segment allocated (id=%d)",
+           lShmId);
+
+   *ShmId = lShmId;
+
+   // Attach segment to address
+   gss_buffer_t databuf = (gss_buffer_t) shmat(lShmId, 0, 0);
+   if ((int) databuf < 0) {
+      ErrorInfo
+          ("GlbsToolStoreToShm: while attaching to shared memory segment (rc=%d)",
+           (int) databuf);
+      return 2;
+   }
+   databuf->length = buffer->length;
+   databuf->value =
+       (void *) ((char *) databuf + sizeof(size_t) + sizeof(void *));
+   memmove(databuf->value, buffer->value, buffer->length);
+
+   // Now we can detach from the shared memory segment ... and release memory we don't anylonger
+   int rc = 0;
+   if ((rc = shmdt((const void *) databuf)) != 0) {
+      ErrorInfo
+          ("GlbsToolStoreToShm: unable to detach from shared memory segment (rc=%d)",
+           rc);
+   }
+   return 0;
+}
+
+
+//______________________________________________________________________________
+char *GlbsToolExpand(char *file)
+{
+   // Test is expansion is needed and return full path file name
+   // (expanded with $HOME).
+   // Returned string must be 'delete[] ed' by the caller.
+
+   char *fret = 0;
+
+   if (file) {
+
+      if (file[0] == '/' || (!getenv("HOME"))) {
+         fret = new char[strlen(file) + 1];
+         strcpy(fret, file);
+      } else {
+         fret = new char[strlen(file) + strlen(getenv("HOME")) + 2];
+         if (file[0] == '~') {
+            sprintf(fret, "%s/%s", getenv("HOME"), file + 1);
+         } else {
+            sprintf(fret, "%s/%s", getenv("HOME"), file);
+         }
+      }
+
+   }
+   return fret;
+}
+
+} // namespace ROOT
diff --git a/rpdutils/src/net.cxx b/rpdutils/src/net.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5b4442a6a9b0d23b27b347d868a840cf73894b48
--- /dev/null
+++ b/rpdutils/src/net.cxx
@@ -0,0 +1,600 @@
+// @(#)root/rpdutils:$Name:  $:$Id: net.cxx,v 1.16 2002/10/28 14:22:51 rdm Exp $
+// Author: Fons Rademakers   12/08/97
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// net                                                                  //
+//                                                                      //
+// Set of network routines for rootd daemon process.                    //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+
+#if defined(linux)
+#   include <features.h>
+#   if __GNU_LIBRARY__ == 6
+#      ifndef R__GLIBC
+#         define R__GLIBC
+#      endif
+#   endif
+#endif
+#if defined(__MACH__) && !defined(__APPLE__)
+#   define R__GLIBC
+#endif
+
+#include "rpdp.h"
+#include "rpderr.h"
+
+#if defined(_AIX) || (defined(__FreeBSD__) && !defined(__alpha__))
+#   define USE_SIZE_T
+#elif defined(R__GLIBC) || (defined(__FreeBSD__) && defined(__alpha__))
+#   define USE_SOCKLEN_T
+#endif
+
+
+namespace ROOT {
+
+extern int     gDebug;
+
+double  gBytesSent = 0;
+double  gBytesRecv = 0;
+
+static char gOpenhost[256] = "????";
+
+static int                tcp_srv_sock;
+static struct sockaddr_in tcp_srv_addr;
+static struct sockaddr_in tcp_cli_addr;
+
+int         gSockFd             = -1;
+char        gFile[kMAXPATHLEN]  = { 0 };
+SigPipe_t   gSigPipeHook        = 0;
+extern int  gParallel;
+
+//______________________________________________________________________________
+const char *NetRemoteHost()
+{
+   return gOpenhost;
+}
+
+//______________________________________________________________________________
+static int Sendn(int sock, const void *buffer, int length)
+{
+   // Send exactly length bytes from buffer.
+
+   if (sock < 0) return -1;
+
+   int n, nsent = 0;
+   const char *buf = (const char *)buffer;
+
+   for (n = 0; n < length; n += nsent) {
+      if ((nsent = send(sock, buf+n, length-n, 0)) <= 0) {
+         Error(gErrFatal, -1, "Sendn: error (sock: %d): errno: %d",
+               sock, GetErrno());
+         return nsent;
+      }
+   }
+
+   gBytesSent += n;
+
+   return n;
+}
+
+//______________________________________________________________________________
+static int Recvn(int sock, void *buffer, int length)
+{
+   // Receive exactly length bytes into buffer. Returns number of bytes
+   // received. Returns -1 in case of error.
+
+   if (sock < 0) return -1;
+
+   int n, nrecv = 0;
+   char *buf = (char *)buffer;
+
+   for (n = 0; n < length; n += nrecv) {
+      while ((nrecv = recv(sock, buf+n, length-n, 0)) == -1 && GetErrno() == EINTR)
+         ResetErrno();   // probably a SIGCLD that was caught
+      if (nrecv < 0) {
+         Error(gErrFatal,-1,"Recvn: error (sock: %d): errno: %d",sock,GetErrno());
+         return nrecv;
+      } else if (nrecv == 0)
+         break;         // EOF
+   }
+
+   gBytesRecv += n;
+
+   return n;
+}
+
+//______________________________________________________________________________
+int NetSendRaw(const void *buf, int len)
+{
+   // Send buffer of len bytes.
+
+   if (gParallel > 0) {
+
+      if (NetParSend(buf, len) != len) {
+         Error(gErrFatal,-1,"NetSendRaw: NetParSend error");
+      }
+
+   } else {
+
+      if (gSockFd == -1) return -1;
+      if (Sendn(gSockFd, buf, len) != len) {
+         Error(gErrFatal,-1,"NetSendRaw: Sendn error");
+      }
+   }
+
+   return len;
+}
+
+//______________________________________________________________________________
+int NetRecvRaw(void *buf, int len)
+{
+   // Receive a buffer of maximum len bytes.
+
+   if (gParallel > 0) {
+
+      if (NetParRecv(buf, len) != len) {
+         Error(gErrFatal,-1,"NetRecvRaw: NetParRecv error");
+      }
+
+   } else {
+
+      if (gSockFd == -1) return -1;
+      if (Recvn(gSockFd, buf, len) < 0) {
+         Error(gErrFatal,-1,"NetRecvRaw: Recvn error (gSockFd: %d)",gSockFd);
+      }
+   }
+
+   return len;
+}
+
+//______________________________________________________________________________
+int NetRecvRaw(int sock, void *buf, int len)
+{
+   // Receive a buffer of maximum len bytes from generic socket sock.
+
+   if (sock == -1) return -1;
+
+   if (Recvn(sock, buf, len) < 0) {
+      Error(gErrFatal,-1,"NetRecvRaw: Recvn error (sock: %d, errno: %d)",sock,GetErrno());
+   }
+
+   return len;
+}
+
+//______________________________________________________________________________
+int NetSend(const void *buf, int len, EMessageTypes kind)
+{
+   // Send buffer of len bytes. Message will be of type "kind".
+
+   int hdr[2];
+   int hlen = sizeof(int) + len;
+   hdr[0] = htonl(hlen);
+   hdr[1] = htonl(kind);
+   if (NetSendRaw(hdr, sizeof(hdr)) < 0)
+      return -1;
+
+   return NetSendRaw(buf, len);
+}
+
+//______________________________________________________________________________
+int NetSend(int code, EMessageTypes kind)
+{
+   // Send integer. Message will be of type "kind".
+
+   int hdr[3];
+   int hlen = sizeof(int) + sizeof(int);
+   hdr[0] = htonl(hlen);
+   hdr[1] = htonl(kind);
+   hdr[2] = htonl(code);
+   return NetSendRaw(hdr, sizeof(hdr));
+}
+
+//______________________________________________________________________________
+int NetSend(const char *msg, EMessageTypes kind)
+{
+   // Send a string. Message will be of type "kind".
+
+   int len = 0;
+
+   if (msg)
+      len = strlen(msg)+1;
+
+   return NetSend(msg, len, kind);
+}
+
+//______________________________________________________________________________
+int NetSendAck()
+{
+   return NetSend(0, kROOTD_ACK);
+}
+
+//______________________________________________________________________________
+int NetSendError(ERootdErrors err)
+{
+   return NetSend(err, kROOTD_ERR);
+}
+
+//______________________________________________________________________________
+int NetRecv(void *&buf, int &len, EMessageTypes &kind)
+{
+   // Receive a buffer. Returns the newly allocated buffer, the length
+   // of the buffer and message type in kind.
+
+   int hdr[2];
+
+   if (NetRecvRaw(hdr, sizeof(hdr)) < 0)
+      return -1;
+
+   len = ntohl(hdr[0]) - sizeof(int);
+   kind = (EMessageTypes) ntohl(hdr[1]);
+   if (len) {
+      buf = new char* [len];
+      return NetRecvRaw(buf, len);
+   }
+   buf = 0;
+   return 0;
+}
+
+//______________________________________________________________________________
+int NetRecv(char *msg, int len, EMessageTypes &kind)
+{
+   // Receive a string of maximum len length. Returns message type in kind.
+   // Return value is msg length.
+
+   int   mlen;
+   char *buf;
+
+   if (NetRecv((void *&)buf, mlen, kind) < 0)
+      return -1;
+
+   if (mlen == 0) {
+      msg[0] = 0;
+      return 0;
+   } else if (mlen > len) {
+      strncpy(msg, buf, len-1);
+      msg[len-1] = 0;
+      mlen = len;
+   } else
+      strcpy(msg, buf);
+
+   delete [] buf;
+
+   return mlen - 1;
+}
+
+//______________________________________________________________________________
+int NetRecv(char *msg, int max)
+{
+   // Simulate TSocket::Recv(char *str, int max).
+
+   EMessageTypes kind;
+
+   return NetRecv((char *)msg, max, kind);
+}
+
+//______________________________________________________________________________
+int NetOpen(int inetdflag, EService service)
+{
+   // Initialize the server's end.
+   // We are passed a flag that says whether or not we are started
+   // by a "master daemon" such as inetd. A master daemon will have
+   // already waited for a message to arrive for us and will have
+   // already set up the connection to the client. If we weren't
+   // started by a master daemon, then we must wait for a client's
+   // request to arrive.
+
+#if defined(USE_SIZE_T)
+   size_t clilen = sizeof(tcp_cli_addr);
+#elif defined(USE_SOCKLEN_T)
+   socklen_t clilen = sizeof(tcp_cli_addr);
+#else
+   int clilen = sizeof(tcp_cli_addr);
+#endif
+
+   if (inetdflag) {
+
+      // When we're fired up by inetd, file decriptors 0, 1 and 2
+      // are sockets to the client.
+
+      gSockFd = 0;
+      if (!getpeername(gSockFd, (struct sockaddr *)&tcp_cli_addr, &clilen)) {
+         struct hostent *hp;
+         if ((hp = gethostbyaddr((const char *)&tcp_cli_addr.sin_addr,
+                                 sizeof(tcp_cli_addr.sin_addr), AF_INET)))
+            strcpy(gOpenhost, hp->h_name);
+         else {
+            struct in_addr *host_addr = (struct in_addr*)&tcp_cli_addr.sin_addr;
+            strcpy(gOpenhost, inet_ntoa(*host_addr));
+         }
+      }
+
+      // Notify, if requested ...
+      if (gDebug > 1)
+         ErrorInfo("NetOpen: fired by inetd: connection from host %s via socket %d", gOpenhost,gSockFd);
+
+      // Set several general performance network options
+      NetSetOptions(service,gSockFd, 65535);
+
+      return 0;
+   }
+
+   // For the concurrent server that's not initiated by inetd,
+   // we have to wait for a connection request to arrive, then
+   // fork a child to handle the client's request.
+   // Beware that the accept() can be interrupted, such as by
+   // a previously spawned child process that has terminated
+   // (for which we caught the SIGCLD signal).
+
+again:
+   int newsock = accept(tcp_srv_sock, (struct sockaddr *)&tcp_cli_addr, &clilen);
+   if (newsock < 0) {
+      if (GetErrno() == EINTR) {
+         ResetErrno();
+         goto again;   // probably a SIGCLD that was caught
+      }
+      Error(gErrSys,kErrFatal, "NetOpen: accept error (errno: %d) ... socket %d",GetErrno(),tcp_srv_sock);
+   }
+
+   struct hostent *hp;
+   if ((hp = gethostbyaddr((const char *)&tcp_cli_addr.sin_addr,
+                           sizeof(tcp_cli_addr.sin_addr), AF_INET)))
+      strcpy(gOpenhost, hp->h_name);
+   else {
+      struct in_addr *host_addr = (struct in_addr*)&tcp_cli_addr.sin_addr;
+      strcpy(gOpenhost, inet_ntoa(*host_addr));
+   }
+
+   // Fork a child process to handle the client's request.
+   // The parent returns the child pid to the caller, which is
+   // probably a concurrent server that'll call us again, to wait
+   // for the next client request to this well-known port.
+
+   int childpid;
+   if ((childpid = fork()) < 0)
+      Error(gErrSys,kErrFatal, "NetOpen: server can't fork");
+   else if (childpid > 0) {    // parent
+      close(newsock);
+      return childpid;
+   }
+
+   // Child process continues here.
+   // First close the original socket so that the parent
+   // can accept any further requests that arrive there.
+   // Then set "gSockFd" in our process to be the descriptor
+   // that we are going to process.
+
+   close(tcp_srv_sock);
+
+   gSockFd = newsock;
+
+   // Notify, if requested ...
+   if (gDebug > 1)
+     ErrorInfo("NetOpen: concurrent server: connection from host %s via socket %d", gOpenhost, gSockFd);
+
+   return 0;
+}
+
+//______________________________________________________________________________
+void NetClose()
+{
+   // Close the network connection.
+
+   if (gParallel > 0) {
+
+      NetParClose();
+
+   } else {
+
+      close(gSockFd);
+      if (gDebug > 0)
+         ErrorInfo("NetClose: host = %s, fd = %d, file = %s", gOpenhost, gSockFd,
+                   gFile);
+      gSockFd = -1;
+   }
+}
+
+//______________________________________________________________________________
+int NetInit(const char *service, int port1, int port2, int tcpwindowsize)
+{
+   // Initialize the network connection for the server, when it has *not*
+   // been invoked by inetd. Used by rootd.
+
+   // We weren't started by a master daemon.
+   // We have to create a socket ourselves and bind our well-known
+   // address to it.
+
+   if (port1 <= 0) {
+      if (service) {
+         struct servent *sp;
+         if ((sp = getservbyname(service, "tcp")) == 0) {
+            fprintf(stderr,       "NetInit: unknown service: %s/tcp\n", service);
+            Error(gErrFatal, kErrFatal, "NetInit: unknown service: %s/tcp", service);
+         }
+         port1 = ntohs(sp->s_port);
+         port2 += port1;   // in this case, port2 is relative to service port
+      } else {
+         fprintf(stderr, "NetInit: must specify either service or port\n");
+         Error(gErrFatal,kErrFatal, "NetInit: must specify either service or port");
+      }
+   }
+
+   // Create the socket and bind our local address so that any client can
+   // send to us.
+
+   if ((tcp_srv_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+      fprintf(stderr,     "NetInit: can't create socket\n");
+      Error(gErrSys,kErrFatal, "NetInit: can't create socket");
+   }
+
+   int val = 1;
+   if (setsockopt(tcp_srv_sock, SOL_SOCKET, SO_REUSEADDR, (char*) &val,
+                  sizeof(val)) == -1) {
+      fprintf(stderr,     "NetInit: can't set SO_REUSEADDR socket option\n");
+      Error(gErrSys, kErrFatal, "NetInit: can't set SO_REUSEADDR socket option");
+   }
+
+   // Set several general performance network options
+   NetSetOptions(kROOTD,tcp_srv_sock, tcpwindowsize);
+
+   memset(&tcp_srv_addr, 0, sizeof(tcp_srv_addr));
+   tcp_srv_addr.sin_family      = AF_INET;
+   tcp_srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+   int port;
+   for (port= port1; port <= port2; port++) {
+      tcp_srv_addr.sin_port = htons(port);
+      if (bind(tcp_srv_sock, (struct sockaddr *) &tcp_srv_addr,
+               sizeof(tcp_srv_addr)) == 0) break;
+   }
+
+   if (port > port2) {
+      fprintf(stderr, "NetInit: can't bind local address to ports %d-%d\n", port1, port2);
+      Error(gErrSys, kErrFatal, "NetInit: can't bind local address to ports %d-%d", port1, port2);
+   }
+
+   printf("ROOTD_PORT=%d\n", port);
+
+   // And set the listen parameter, telling the system that we're
+   // ready to accept incoming connection requests.
+
+   //   listen(tcp_srv_sock, 5);
+   if (listen(tcp_srv_sock, 5)==-1) {
+      ErrorInfo("NetInit: listen: error (errno: %d)",GetErrno());
+   }
+
+   if (gDebug > 0)
+      ErrorInfo("NetInit: socket %d listening on port %d", tcp_srv_sock,
+                ntohs(tcp_srv_addr.sin_port));
+
+   return tcp_srv_sock;
+}
+
+//______________________________________________________________________________
+void NetInit(const char *service, int port, int tcpwindowsize)
+{
+   // Initialize the network connection for the server, when it has *not*
+   // been invoked by inetd. Used by proofd.
+
+   // We weren't started by a master daemon.
+   // We have to create a socket ourselves and bind our well-known
+   // address to it.
+
+   memset(&tcp_srv_addr, 0, sizeof(tcp_srv_addr));
+   tcp_srv_addr.sin_family      = AF_INET;
+   tcp_srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+   if (service) {
+
+      if (port > 0)
+         tcp_srv_addr.sin_port = htons(port);
+      else {
+         struct servent *sp;
+         if ((sp = getservbyname(service, "tcp")) == 0)
+            Error(gErrFatal,-1,"NetInit: unknown service: %s/tcp", service);
+         tcp_srv_addr.sin_port = sp->s_port;
+      }
+
+   } else {
+
+      if (port <= 0)
+         Error(gErrFatal,-1,"NetInit: must specify either service or port");
+      tcp_srv_addr.sin_port = htons(port);
+
+   }
+
+   // Create the socket and bind our local address so that any client can
+   // send to us.
+
+   if ((tcp_srv_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+      Error(gErrSys,-1,"NetInit: can't create socket");
+
+   int val = 1;
+   if (setsockopt(tcp_srv_sock, SOL_SOCKET, SO_REUSEADDR, (char*) &val,
+                  sizeof(val)) == -1)
+      Error(gErrSys,-1,"NetInit: can't set SO_REUSEADDR socket option");
+
+   // Set several general performance network options
+   NetSetOptions(kPROOFD,tcp_srv_sock, tcpwindowsize);
+
+   if (bind(tcp_srv_sock, (struct sockaddr *) &tcp_srv_addr,
+            sizeof(tcp_srv_addr)) < 0)
+      Error(gErrSys,-1,"NetInit: can't bind local address (sock: %d) : errno: %d",tcp_srv_sock,GetErrno());
+
+   // And set the listen parameter, telling the system that we're
+   // ready to accept incoming connection requests.
+
+   listen(tcp_srv_sock, 5);
+
+   if (gDebug > 0)
+      ErrorInfo("NetInit: socket %d listening on port %d", tcp_srv_sock,
+                ntohs(tcp_srv_addr.sin_port));
+}
+
+//______________________________________________________________________________
+void NetSetOptions(EService serv, int sock, int tcpwindowsize)
+{
+   // Set some options for network socket.
+
+   int val = 1;
+
+   if (serv == kROOTD) {
+      if (!setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val))) {
+         if (gDebug > 0) ErrorInfo("NetSetOptions: set TCP_NODELAY");
+      }
+      if (!setsockopt(sock, SOL_SOCKET,  SO_KEEPALIVE, (char *)&val, sizeof(val))) {
+         if (gDebug > 0) ErrorInfo("NetSetOptions: set SO_KEEPALIVE");
+         if (gSigPipeHook != 0) signal(SIGPIPE, (*gSigPipeHook));   // handle SO_KEEPALIVE failure
+      }
+   }
+
+   val = tcpwindowsize;
+   if (!setsockopt(sock, SOL_SOCKET,  SO_SNDBUF, (char *)&val, sizeof(val))) {
+      if (gDebug > 0) ErrorInfo("NetSetOptions: set SO_SNDBUF %d", val);
+   }
+   if (!setsockopt(sock, SOL_SOCKET,  SO_RCVBUF, (char *)&val, sizeof(val))) {
+      if (gDebug > 0) ErrorInfo("NetSetOptions: set SO_RCVBUF %d", val);
+   }
+
+   if (gDebug > 0) {
+#if defined(USE_SIZE_T)
+      size_t optlen = sizeof(val);
+#elif defined(USE_SOCKLEN_T)
+      socklen_t optlen = sizeof(val);
+#else
+      int optlen = sizeof(val);
+#endif
+      if (serv == kROOTD) {
+         getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, &optlen);
+         ErrorInfo("NetSetOptions: get TCP_NODELAY: %d", val);
+         getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, &optlen);
+         ErrorInfo("NetSetOptions: get SO_KEEPALIVE: %d", val);
+      }
+      getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, &optlen);
+      ErrorInfo("NetSetOptions: get SO_SNDBUF: %d", val);
+      getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, &optlen);
+      ErrorInfo("NetSetOptions: get SO_RCVBUF: %d", val);
+   }
+}
+
+} // namespace ROOT
diff --git a/rpdutils/src/netpar.cxx b/rpdutils/src/netpar.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2dbf2bbeb7dde185ee331a4c2cabb28b096e376e
--- /dev/null
+++ b/rpdutils/src/netpar.cxx
@@ -0,0 +1,280 @@
+// @(#)root/rpdutils:$Name:  $:$Id: netpar.cxx,v 1.8 2003/04/06 21:30:13 rdm Exp $
+// Author: Fons Rademakers   06/02/2001
+
+/*************************************************************************
+ * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// netpar                                                               //
+//                                                                      //
+// Set of parallel network routines for rootd daemon process. To be     //
+// used when remote uses TPSocket to connect to rootd.                  //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#if defined(_AIX)
+#include <strings.h>
+#endif
+
+#if defined(linux)
+#   include <features.h>
+#   if __GNU_LIBRARY__ == 6
+#      ifndef R__GLIBC
+#         define R__GLIBC
+#      endif
+#   endif
+#endif
+#if defined(__MACH__) && !defined(__APPLE__)
+#   define R__GLIBC
+#endif
+
+#include "RConfig.h"
+#include "rootdp.h"
+
+#if defined(_AIX) || (defined(__FreeBSD__) && !defined(__alpha__)) || \
+    defined(R__SUNGCC3)
+#   define USE_SIZE_T
+#elif defined(R__GLIBC) || (defined(__FreeBSD__) && defined(__alpha__))
+#   define USE_SOCKLEN_T
+#endif
+
+namespace ROOT {
+
+int gParallel = 0;
+
+extern int    gDebug;
+
+static int    gMaxFd;
+static int   *gPSockFd;
+static int   *gWriteBytesLeft;
+static int   *gReadBytesLeft;
+static char **gWritePtr;
+static char **gReadPtr;
+static fd_set gFdSet;
+
+
+//______________________________________________________________________________
+static void InitSelect(int nsock)
+{
+   // Setup select masks.
+
+   FD_ZERO(&gFdSet);
+   gMaxFd = -1;
+   for (int i = 0; i < nsock; i++) {
+      FD_SET(gPSockFd[i], &gFdSet);
+      if (gPSockFd[i] > gMaxFd)
+         gMaxFd = gPSockFd[i];
+   }
+}
+
+//______________________________________________________________________________
+int NetParSend(const void *buf, int len)
+{
+   // Send buffer of specified length over the parallel sockets.
+   // Returns len in case of success and -1 in case of error.
+
+   int i, alen = len, nsock = gParallel;
+
+   // If data buffer is < 4K use only one socket
+   if (len < 4096)
+      nsock = 1;
+
+   for (i = 0; i < nsock; i++) {
+      gWriteBytesLeft[i] = len/nsock;
+      gWritePtr[i] = (char *)buf + (i*gWriteBytesLeft[i]);
+   }
+   gWriteBytesLeft[i-1] += len%nsock;
+
+   InitSelect(nsock);
+
+   // Send the data on the parallel sockets
+   while (len > 0) {
+
+      fd_set writeReady = gFdSet;
+
+      int isel = select(gMaxFd+1, 0, &writeReady, 0, 0);
+      if (isel < 0) {
+         ErrorInfo("NetParSend: error on select");
+         return -1;
+      }
+
+      for (i = 0; i < nsock; i++) {
+         if (FD_ISSET(gPSockFd[i], &writeReady)) {
+            if (gWriteBytesLeft[i] > 0) {
+               int ilen;
+again:
+               ilen = send(gPSockFd[i], gWritePtr[i], gWriteBytesLeft[i], 0);
+               if (ilen < 0) {
+                  if (GetErrno() == EAGAIN)
+                     goto again;
+                  ErrorInfo("NetParSend: error sending for socket %d (%d)",
+                            i, gPSockFd[i]);
+                  return -1;
+               }
+               gWriteBytesLeft[i] -= ilen;
+               gWritePtr[i] += ilen;
+               len -= ilen;
+            }
+         }
+      }
+   }
+
+   return alen;
+}
+
+//______________________________________________________________________________
+int NetParRecv(void *buf, int len)
+{
+   // Receive buffer of specified length over parallel sockets.
+   // Returns len in case of success and -1 in case of error.
+
+   int i, alen = len, nsock = gParallel;
+
+   // If data buffer is < 4K use only one socket
+   if (len < 4096)
+      nsock = 1;
+
+   for (i = 0; i < nsock; i++) {
+      gReadBytesLeft[i] = len/nsock;
+      gReadPtr[i] = (char *)buf + (i*gReadBytesLeft[i]);
+   }
+   gReadBytesLeft[i-1] += len%nsock;
+
+   InitSelect(nsock);
+
+   // Recieve the data on the parallel sockets
+   while (len > 0) {
+
+      fd_set readReady = gFdSet;
+
+      int isel = select(gMaxFd+1, &readReady, 0, 0, 0);
+      if (isel < 0) {
+         ErrorInfo("NetParRecv: error on select");
+         return -1;
+      }
+
+      for (i = 0; i < nsock; i++) {
+         if (FD_ISSET(gPSockFd[i], &readReady)) {
+            if (gReadBytesLeft[i] > 0) {
+               int ilen = recv(gPSockFd[i], gReadPtr[i], gReadBytesLeft[i], 0);
+               if (ilen < 0) {
+                  ErrorInfo("NetParRecv: error receiving for socket %d (%d)",
+                            i, gPSockFd[i]);
+                  return -1;
+               } else if (ilen == 0) {
+                  ErrorInfo("NetParRecv: EOF on socket %d (%d)",
+                            i, gPSockFd[i]);
+                  return 0;
+               }
+               gReadBytesLeft[i] -= ilen;
+               gReadPtr[i] += ilen;
+               len -= ilen;
+            }
+         }
+      }
+   }
+
+   return alen;
+}
+
+//______________________________________________________________________________
+int NetParOpen(int port, int size)
+{
+   // Open size parallel sockets back to client. Returns 0 in case of error,
+   // and number of parallel sockets in case of success.
+
+   struct sockaddr_in remote_addr;
+   memset(&remote_addr, 0, sizeof(remote_addr));
+
+#if defined(USE_SIZE_T)
+   size_t remlen = sizeof(remote_addr);
+#elif defined(USE_SOCKLEN_T)
+   socklen_t remlen = sizeof(remote_addr);
+#else
+   int remlen = sizeof(remote_addr);
+#endif
+
+   if (!getpeername(gSockFd, (struct sockaddr *)&remote_addr, &remlen)) {
+      remote_addr.sin_family = AF_INET;
+      remote_addr.sin_port   = htons(port);
+
+      gPSockFd = new int[size];
+
+      for (int i = 0; i < size; i++) {
+         if ((gPSockFd[i] = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+            Error(gErrSys, kErrFatal, "NetParOpen: can't create socket %d (%d)",
+                     i, gPSockFd[i]);
+
+         NetSetOptions(kROOTD, gPSockFd[i], 65535);
+
+         if (connect(gPSockFd[i], (struct sockaddr *)&remote_addr, remlen) < 0)
+            Error(gErrSys, kErrFatal, "NetParOpen: can't connect socket %d (%d)",
+                  i, gPSockFd[i]);
+
+         // Set non-blocking
+         int val;
+         if ((val = fcntl(gPSockFd[i], F_GETFL, 0)) < 0)
+            Error(gErrSys, kErrFatal, "NetParOpen: can't get control flags");
+         val |= O_NONBLOCK;
+         if (fcntl(gPSockFd[i], F_SETFL, val) < 0)
+            Error(gErrSys, kErrFatal, "NetParOpen: can't make socket non blocking");
+      }
+
+      gWriteBytesLeft = new int[size];
+      gReadBytesLeft  = new int[size];
+      gWritePtr       = new char*[size];
+      gReadPtr        = new char*[size];
+
+      // Close initial setup socket
+      NetClose();
+
+      gParallel = size;
+
+      if (gDebug > 0)
+         ErrorInfo("NetParOpen: %d parallel connections established", size);
+
+   } else
+      Error(gErrSys, kErrFatal, "NetParOpen: can't get peer name");
+
+   return gParallel;
+}
+
+//______________________________________________________________________________
+void NetParClose()
+{
+   // Close parallel sockets.
+
+   for (int i = 0; i < gParallel; i++)
+      close(gPSockFd[i]);
+
+   delete [] gPSockFd;
+   delete [] gWriteBytesLeft;
+   delete [] gReadBytesLeft;
+   delete [] gWritePtr;
+   delete [] gReadPtr;
+
+   gParallel = 0;
+
+   if (gDebug > 0)
+      ErrorInfo("NetParClose: file = %s", gFile);
+}
+
+} // namespace ROOT
diff --git a/rpdutils/src/rpdutils.cxx b/rpdutils/src/rpdutils.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7fb87f7009351ef3b69ca35199640fc523f4a763
--- /dev/null
+++ b/rpdutils/src/rpdutils.cxx
@@ -0,0 +1,3435 @@
+// @(#)root/rpdutils:$Name:  $:$Id: daemon.cxx,v 1.5 2002/10/28 14:22:51 rdm Exp $
+// Author: Gerardo Ganis    7/4/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// rpdutils                                                             //
+//                                                                      //
+// Set of utilities for rootd/proofd daemon authentication.             //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include "config.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <netdb.h>
+#if defined(__alpha) && !defined(linux)
+#   ifdef _XOPEN_SOURCE
+#      if _XOPEN_SOURCE+0 > 0
+#         define R__TRUE64
+#      endif
+#   endif
+#include <sys/mount.h>
+#ifndef R__TRUE64
+extern "C" int fstatfs(int file_descriptor, struct statfs *buffer);
+#endif
+#elif defined(__APPLE__)
+#include <sys/mount.h>
+extern "C" int fstatfs(int file_descriptor, struct statfs *buffer);
+#elif defined(linux) || defined(__hpux)
+#include <sys/vfs.h>
+#elif defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/mount.h>
+#else
+#include <sys/statfs.h>
+#endif
+
+#if defined(linux) || defined(__hpux) || defined(_AIX) || defined(__alpha) || \
+    defined(__sun) || defined(__sgi) || defined(__FreeBSD__) || \
+    defined(__APPLE__)
+#define HAVE_MMAP
+#endif
+
+#ifdef HAVE_MMAP
+#   include <sys/mman.h>
+#ifndef MAP_FILE
+#define MAP_FILE 0              /* compatability flag */
+#endif
+#endif
+
+#if defined(linux)
+#   include <features.h>
+#   if __GNU_LIBRARY__ == 6
+#      ifndef R__GLIBC
+#         define R__GLIBC
+#      endif
+#   endif
+#endif
+#if defined(__MACH__) && !defined(__APPLE__)
+#   define R__GLIBC
+#endif
+
+#if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || defined(__APPLE__)
+#include <sys/file.h>
+#define lockf(fd, op, sz)   flock((fd), (op))
+#ifndef F_LOCK
+#define F_LOCK             (LOCK_EX | LOCK_NB)
+#endif
+#ifndef F_ULOCK
+#define F_ULOCK             LOCK_UN
+#endif
+#endif
+
+#if defined(linux) || defined(__sun) || defined(__sgi) || \
+    defined(_AIX) || defined(__FreeBSD__) || defined(__APPLE__) || \
+    defined(__MACH__)
+#include <grp.h>
+#include <sys/types.h>
+#include <signal.h>
+#endif
+
+#if defined(__sun) || defined(R__GLIBC)
+#include <crypt.h>
+#endif
+
+#if defined(__osf__) || defined(__sgi)
+extern "C" char *crypt(const char *, const char *);
+#endif
+
+#if defined(__alpha) && !defined(linux) && !defined(__FreeBSD__)
+extern "C" int initgroups(const char *name, int basegid);
+#endif
+
+#if defined(__sgi) && !defined(__GNUG__) && (SGI_REL<62)
+extern "C" {
+   int seteuid(int euid);
+   int setegid(int egid);
+}
+#endif
+#if defined(_AIX)
+extern "C" {
+   //int initgroups(const char *name, int basegid);
+   int seteuid(uid_t euid);
+   int setegid(gid_t egid);
+}
+#endif
+#if defined(__sun)
+#ifndef R__SHADOWPW
+#define R__SHADOWPW
+#endif
+#endif
+#ifdef R__SHADOWPW
+#include <shadow.h>
+#endif
+#ifdef R__AFS
+//#include <afs/kautils.h>
+#define KA_USERAUTH_VERSION 1
+#define KA_USERAUTH_DOSETPAG 0x10000
+#define NOPAG  0xffffffff
+extern "C" int ka_UserAuthenticateGeneral(int, char *, char *, char *,
+                                          char *, int, int, int, char **);
+#endif
+
+#ifdef R__SRP
+extern "C" {
+#include <t_pwd.h>
+#include <t_server.h>
+}
+#endif
+#ifdef R__KRB5
+extern "C" {
+#include <com_err.h>
+#include <krb5.h>
+   int krb5_net_write(krb5_context, int, const char *, int);
+}
+#include <string>
+extern krb5_deltat krb5_clockskew;
+#endif
+
+#include "rpdp.h"
+extern "C" {
+#include "rsadef.h"
+#include "rsalib.h"
+}
+namespace ROOT {//--- Globals ------------------------------------------------------------------
+const char kRootdPass[]  = ".rootdpass";
+const char kSRootdPass[] = ".srootdpass";
+const char kMethods[]    = "usrpwd srp    krb5   globus ssh    uidgid";
+
+// Statics
+int gDebug = 0;
+static int gAllowMeth[kMAXSEC];
+static int gTriedMeth[kMAXSEC];
+static int gHaveMeth[kMAXSEC];
+int gRootLog = 0;
+static char gRpdAuthTab[kMAXPATHLEN] = { 0 };  // keeps track of authentication info
+
+// To control user access
+char *gUserAllow[kMAXSEC] = { 0 };
+char *gUserIgnore[kMAXSEC] = { 0 };
+unsigned int gUserAlwLen[kMAXSEC] = { 0 };
+unsigned int gUserIgnLen[kMAXSEC] = { 0 };
+
+
+char gAltSRPPass[kMAXPATHLEN] = { 0 };
+char gAnonUser[64] = "rootd";
+char gAuthAllow[kMAXPATHLEN] = "/etc/root/rpdauth.allow"; // defines host-specific allowed methods for auth
+char gExecDir[kMAXPATHLEN] = { 0 }; // needed to localize ssh2rpd
+char gFileLog[kMAXPATHLEN] = { 0 };
+char gOpenHost[256] = "????";       // same length as in net.cxx ...
+char gPasswd[64] = { 0 };
+char gService[10] = "????";         // "rootd" or "proofd", defined in proofd/rootd.cxx ...
+char gTmpDir[kMAXPATHLEN] = { 0 };  // RW dir for temporary files
+char gUser[64] = { 0 };
+
+int gAltSRP = 0;
+int gAnon = 0;
+int gAuth = 0;
+int gClientProtocol = 0;
+int gGlobus = -1;
+int gNumAllow = -1;
+int gNumLeft = -1;
+int gOffSet = -1;
+int gRemPid = -1;
+int gReUseAllow = 0x1F;  // define methods for which previous auth can be reused
+int gSshdPort = 22;
+
+// Globals of internal linkage
+int  gSec = -1;
+int  gRSAKey = 0;
+rsa_NUMBER gRSA_n;
+rsa_NUMBER gRSA_d;
+char gPubKey[kMAXPATHLEN] = { 0 };
+int  gMethInit = 0;
+int  gCryptRequired = -1;
+int  gReUseRequired = -1;
+
+} //namespace ROOT
+
+#ifdef R__KRB5
+krb5_keytab gKeytab = 0;        // to allow specifying on the command line
+krb5_context gKcontext;
+#endif
+
+#ifdef R__GLBS
+int gShmIdCred = -1;            // global, to pass the shm ID to proofserv
+gss_ctx_id_t GlbContextHandle = GSS_C_NO_CONTEXT;
+#endif
+
+// Masks for authentication methods
+const int kAUTH_CLR_MSK = 0x1;
+const int kAUTH_SRP_MSK = 0x2;
+const int kAUTH_KRB_MSK = 0x4;
+const int kAUTH_GLB_MSK = 0x8;
+const int kAUTH_SSH_MSK = 0x10;
+
+#define SafeDelete(p) { if (p) { delete p; p = 0; } }
+
+namespace ROOT {
+
+//______________________________________________________________________________
+void RpdSetDebugFlag(int Debug)
+{
+   // Change the value of the static gDebug to Debug.
+
+   gDebug = Debug;
+   if (gDebug > 2)
+      ErrorInfo("RpdSetDebugFlag: gDebug set to %d", gDebug);
+}
+
+//______________________________________________________________________________
+void RpdSetRootLogFlag(int RootLog)
+{
+   // Change the value of the static gRootLog to RootLog.
+   // Recognized values:
+   //                       0      log to syslog (for root started daemons)
+   //                       1      log to stderr ( for user started daemons)
+
+   gRootLog = RootLog;
+   if (gDebug > 2)
+      ErrorInfo("RpdSetRootLogFlag: gRootLog set to %d", gRootLog);
+}
+
+//______________________________________________________________________________
+void RpdSetAuthTabFile(char *AuthTabFile)
+{
+   // Change the value of the static gRpdAuthTab to AuthTabFile.
+
+   strcpy(gRpdAuthTab, AuthTabFile);
+   if (gDebug > 2)
+      ErrorInfo("RpdSetAuthTabFile: gRpdAuthTab set to '%s'", AuthTabFile);
+}
+
+//______________________________________________________________________________
+int RpdGetAuthMethod(int kind)
+{
+   int Meth = -1;
+
+   if (kind == kROOTD_USER)
+      Meth = 0;
+   if (kind == kROOTD_SRPUSER)
+      Meth = 1;
+   if (kind == kROOTD_KRB5)
+      Meth = 2;
+   if (kind == kROOTD_GLOBUS)
+      Meth = 3;
+   if (kind == kROOTD_SSH)
+      Meth = 4;
+   if (kind == kROOTD_RFIO)
+      Meth = 5;
+
+   return Meth;
+}
+
+//______________________________________________________________________________
+int RpdUpdateAuthTab(int opt, char *line, char **token)
+{
+   // Update tab file.
+   // If opt=0 then eliminates all inactive entries,
+   // if opt=1 append 'line'.
+   // Returns offset for 'line' (opt=1) or -1 if any error occurs
+   // and token.
+
+   int retval = -1;
+   int itab = 0;
+   char fbuf[kMAXPATHLEN];
+
+   if (gDebug > 2)
+      ErrorInfo("RpdUpdateAuthTab: analyzing: opt: %d, line: %s", opt,
+                line);
+
+   if (opt == -1) {
+      if (!access(gRpdAuthTab, F_OK)) {
+         // Save the content ...
+         char *bak = new char[strlen(gRpdAuthTab) + 10];
+         sprintf(bak, "%s.bak", gRpdAuthTab);
+         FILE *fbak = fopen(bak, "w");
+         FILE *ftab = fopen(gRpdAuthTab, "r");
+         char buf[kMAXPATHLEN];
+         while (fgets(buf, sizeof(buf), ftab)) {
+            fprintf(fbak, "%s", buf);
+         }
+         fclose(fbak);
+         fclose(ftab);
+         // ... before deleting the original ...
+         unlink(gRpdAuthTab);
+         SafeDelete(bak);
+      }
+      return 0;
+   } else if (opt == 0) {
+      // Open file for update
+      itab = open(gRpdAuthTab, O_RDWR | O_CREAT, 0666);
+      if (itab == -1) {
+         ErrorInfo
+             ("RpdUpdateAuthTab: opt=%d: error opening %s (errno: %d)",
+              opt, gRpdAuthTab, GetErrno());
+         return retval;
+      }
+      // override umask setting
+      fchmod(itab, 0666);
+      // lock tab file
+      if (lockf(itab, F_LOCK, (off_t) 1) == -1) {
+         ErrorInfo
+             ("RpdUpdateAuthTab: opt=%d: error locking %s (errno: %d)",
+              opt, gRpdAuthTab, GetErrno());
+         close(itab);
+         return retval;
+      }
+      // File is open: get FILE descriptor
+      FILE *ftab = fdopen(itab, "a");
+      // and set indicator to beginning
+      lseek(itab, 0, SEEK_SET);
+
+      // Now scan over entries
+      int pr = 0, pw = 0;
+      int lsec, act;
+      char line[kMAXPATHLEN], dumm[kMAXPATHLEN];
+      bool good = 0, fwr = 0;
+
+      while (fgets(line, sizeof(line), ftab)) {
+         pr = lseek(itab, 0, SEEK_CUR);
+         sscanf(line, "%d %d %s", &lsec, &act, dumm);
+         good = (act == 1);
+         if (good) {
+            if (fwr) {
+               lseek(itab, pw, SEEK_SET);
+               sprintf(fbuf, "%s\n", line);
+               while (write(itab, fbuf, strlen(fbuf)) < 0
+                      && GetErrno() == EINTR)
+                  ResetErrno();
+               pw = lseek(itab, 0, SEEK_CUR);
+               lseek(itab, pr, SEEK_SET);
+            } else
+               pw = lseek(itab, 0, SEEK_CUR);
+         } else {
+            fwr = 1;
+         }
+      }
+
+      // Truncate file to new length
+      ftruncate(itab, pw);
+
+      retval = 0;
+
+   } else if (opt == 1) {
+      // open file for append
+      if (gDebug > 2)
+         ErrorInfo("RpdUpdateAuthTab: opening file %s", gRpdAuthTab);
+
+      if (access(gRpdAuthTab, F_OK)) {
+         itab = open(gRpdAuthTab, O_RDWR | O_CREAT, 0666);
+         if (itab == -1) {
+            ErrorInfo
+                ("RpdUpdateAuthTab: opt=%d: error opening %s (errno: %d)",
+                 opt, gRpdAuthTab, GetErrno());
+            return retval;
+         }
+         // override umask setting
+         fchmod(itab, 0666);
+      } else {
+         itab = open(gRpdAuthTab, O_RDWR);
+      }
+      if (itab == -1) {
+         ErrorInfo
+             ("RpdUpdateAuthTab: opt=%d: error opening or creating %s (errno: %d)",
+              opt, gRpdAuthTab, GetErrno());
+         return retval;
+      }
+      // lock tab file
+      if (gDebug > 2)
+         ErrorInfo("RpdUpdateAuthTab: locking file %s", gRpdAuthTab);
+      if (lockf(itab, F_LOCK, (off_t) 1) == -1) {
+         ErrorInfo
+             ("RpdUpdateAuthTab: opt=%d: error locking %s (errno: %d)",
+              opt, gRpdAuthTab, GetErrno());
+         close(itab);
+         return retval;
+      }
+      // saves offset
+      retval = lseek(itab, 0, SEEK_END);
+      if (gDebug > 2)
+         ErrorInfo("RpdUpdateAuthTab: offset is %d", retval);
+
+      // Generate token
+      *token = RpdGetRandString(3, 8);   // 8 crypt-like chras
+      char *CryptToken = crypt(*token, *token);
+      sprintf(fbuf, "%s %s\n", line, CryptToken);
+      if (gDebug > 2)
+         ErrorInfo("RpdUpdateAuthTab: token: '%s'", CryptToken);
+
+      // adds line
+      while (write(itab, fbuf, strlen(fbuf)) < 0 && GetErrno() == EINTR)
+         ResetErrno();
+
+   } else {
+      ErrorInfo("RpdUpdateAuthTab: unrecognized option (opt= %d)", opt);
+      return retval;
+   }
+
+   // unlock the file
+   lseek(itab, 0, SEEK_SET);
+   if (lockf(itab, F_ULOCK, (off_t) 1) == -1) {
+      ErrorInfo("RpdUpdateAuthTab: error unlocking %s", gRpdAuthTab);
+   }
+   // closing file ...
+   close(itab);
+
+   return retval;
+}
+
+//______________________________________________________________________________
+int RpdCleanupAuthTab(char *Host, int RemId)
+{
+   // Cleanup (set inactive) entries in tab file,
+   // if Host="all" or RemId=0 discard all entries.
+   // Return number of entries not cleaned properly ...
+
+   int retval = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdCleanupAuthTab: cleaning for Host: '%s', RemId:%d",
+                Host, RemId);
+
+   // Open file for update
+   int itab = open(gRpdAuthTab, O_RDWR);
+   if (itab == -1) {
+      ErrorInfo("RpdCleanupAuthTab: error opening %s (errno: %d)",
+                gRpdAuthTab, GetErrno());
+      //     return retval;
+      return -1;
+   }
+   // lock tab file
+   if (lockf(itab, F_LOCK, (off_t) 1) == -1) {
+      ErrorInfo("RpdCleanupAuthTab: error locking %s (errno: %d)",
+                gRpdAuthTab, GetErrno());
+      close(itab);
+      //     return retval;
+      return -2;
+   }
+   // File is open: get FILE descriptor
+   FILE *ftab = fdopen(itab, "r+");
+
+   // Now scan over entries
+   int pr = 0, pw = 0;
+   int nw, lsec, act, parid, remid, pkey;
+   char line[kMAXPATHLEN], line1[kMAXPATHLEN], host[kMAXPATHLEN];
+   char dumm[kMAXPATHLEN], user[kMAXPATHLEN];
+#ifdef R__GLBS
+   char subj[kMAXPATHLEN];
+#endif
+
+   // and set indicator to beginning
+   pr = lseek(itab, 0, SEEK_SET);
+   pw = pr;
+   while (fgets(line, sizeof(line), ftab)) {
+      pr += strlen(line);
+      if (gDebug > 2)
+         ErrorInfo("RpdCleanupAuthTab: pr:%d pw:%d (line:%s)", pr, pw,
+                   line);
+
+      nw = sscanf(line, "%d %d %d %d %d %s %s %s", &lsec, &act, &pkey,
+                  &parid, &remid, host, user, dumm);
+      if (nw > 5) {
+         if (!strcmp(Host, "all") || (RemId == 0) ||
+             (!strcmp(Host, host) && (RemId == remid))) {
+
+            // Delete Public Key file
+            char PubKeyFile[kMAXPATHLEN];
+            sprintf(PubKeyFile, "%s/rpk_%d", gTmpDir, pw);
+
+            if (gDebug > 0) {
+              struct stat st;
+              if (stat(PubKeyFile, &st) == 0) {
+                ErrorInfo("RpdCleanupAuthTab: file uid:%d gid:%d",st.st_uid,st.st_gid);
+              }
+              ErrorInfo("RpdCleanupAuthTab: proc uid:%d gid:%d",getuid(),getgid());
+            }
+
+            if (unlink(PubKeyFile) == -1) {
+               if (gDebug > 0) {
+                  ErrorInfo
+                     ("RpdCleanupAuthTab: problems unlinking pub key file '%s' (errno: %d)",
+                      PubKeyFile,GetErrno());
+               }
+            }
+
+            if (act == 1) {
+               if (lsec == 3) {
+#ifdef R__GLBS
+                  int shmid;
+                  nw = sscanf(line, "%d %d %d %d %d %s %s %d %s %s", &lsec,
+                              &act, &pkey, &parid, &remid, host, user,
+                              &shmid, subj, dumm);
+                  struct shmid_ds shm_ds;
+                  if (shmctl(shmid, IPC_RMID, &shm_ds) == -1) {
+                     ErrorInfo
+                         ("RpdCleanupAuthTab: unable to mark shared memory segment %d for desctruction (errno: %d)",
+                          shmid, GetErrno());
+                     retval++;
+                  }
+                  sprintf(line1, "%d %d %d %d %d %s %s %d %s %s\n", lsec,
+                          0, pkey, parid, remid, host, user, shmid, subj,
+                          dumm);
+#else
+                  ErrorInfo
+                      ("RpdCleanupAuthTab: compiled without Globus support: you shouldn't have got here!");
+                  sprintf(line1,
+                          "%d %d %d %d %d %s %s %s - WARNING: bad line\n",
+                          lsec, 0, pkey, parid, remid, host, user, dumm);
+#endif
+               } else {
+                  sprintf(line1, "%d %d %d %d %d %s %s %s\n", lsec, 0,
+                          pkey, parid, remid, host, user, dumm);
+               }
+               lseek(itab, pw, SEEK_SET);
+               while (write(itab, line1, strlen(line1)) < 0
+                      && GetErrno() == EINTR)
+                  ResetErrno();
+               lseek(itab, pr, SEEK_SET);
+            }
+         }
+      }
+      pw = pr;
+   }
+
+   // unlock the file
+   lseek(itab, 0, SEEK_SET);
+   if (lockf(itab, F_ULOCK, (off_t) 1) == -1) {
+      ErrorInfo("RpdCleanupAuthTab: error unlocking %s", gRpdAuthTab);
+   }
+   // closing file ...
+   close(itab);
+
+   return retval;
+}
+
+//______________________________________________________________________________
+int RpdCheckAuthTab(int Sec, char *User, char *Host, int RemId, int *OffSet)
+{
+   // Check authentication entry in tab file.
+
+   int retval = 0;
+   bool GoodOfs = 0;
+   int ofs = *OffSet >= 0 ? *OffSet : 0;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckAuthTab: analyzing: %d %s %s %d %d", Sec, User,
+                Host, RemId, *OffSet);
+
+   // First check if file exists and can be read
+   if (access(gRpdAuthTab, F_OK))
+      return retval;
+   if (access(gRpdAuthTab, R_OK)) {
+      ErrorInfo("RpdCheckAuthTab: can't read file %s (errno: %d)",
+                gRpdAuthTab, GetErrno());
+      return retval;
+   }
+   // Open file
+   int itab = open(gRpdAuthTab, O_RDWR);
+   if (itab == -1) {
+      ErrorInfo("RpdCheckAuthTab: error opening %s (errno: %d)",
+                gRpdAuthTab, GetErrno());
+      return retval;
+   }
+   // lock tab file
+   if (lockf(itab, F_LOCK, (off_t) 1) == -1) {
+      ErrorInfo("RpdCheckAuthTab: error locking %s (errno: %d)",
+                gRpdAuthTab, GetErrno());
+      close(itab);
+      return retval;
+   }
+   // File is open: set position at wanted location
+   FILE *ftab = fdopen(itab, "r+");
+   fseek(ftab, ofs, SEEK_SET);
+
+   // Now read the entry
+   char line[kMAXPATHLEN];
+   fgets(line, sizeof(line), ftab);
+
+   // and parse its content according to auth method
+   int lsec, act, parid, remid, shmid;
+   char host[kMAXPATHLEN], user[kMAXPATHLEN], subj[kMAXPATHLEN],
+       dumm[kMAXPATHLEN], tkn[20];
+   int nw =
+       sscanf(line, "%d %d %d %d %d %s %s %s %s", &lsec, &act, &gRSAKey,
+              &parid, &remid, host, user, tkn, dumm);
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckAuthTab: found line: %s", line);
+   if (nw > 5) {
+      if ((lsec == Sec)) {
+         if (lsec == 3) {
+            sscanf(line, "%d %d %d %d %d %s %s %d %s %s %s", &lsec, &act,
+                   &gRSAKey, &parid, &remid, host, user, &shmid, subj, tkn,
+                   dumm);
+            //if ((parid == getppid()) && (remid == RemId)
+            if ((remid == RemId)
+                && !strcmp(host, Host) && !strcmp(subj, User))
+               GoodOfs = 1;
+         } else {
+            //if ((parid == getppid()) && (remid == RemId) &&
+            if ((remid == RemId) &&
+                !strcmp(host, Host) && !strcmp(user, User))
+               GoodOfs = 1;
+         }
+      }
+   }
+   if (!GoodOfs) {
+      // Tab may have been cleaned in the meantime ... try a scan
+      fseek(ftab, 0, SEEK_SET);
+      ofs = ftell(ftab);
+      while (fgets(line, sizeof(line), ftab)) {
+         nw = sscanf(line, "%d %d %d %d %d %s %s %s %s", &lsec, &act,
+                     &gRSAKey, &parid, &remid, host, user, tkn, dumm);
+         if (gDebug > 2)
+            ErrorInfo("RpdCheckAuthTab: found line: %s", line);
+         if (nw > 5) {
+            if (lsec == Sec) {
+               if (lsec == 3) {
+                  sscanf(line, "%d %d %d %d %d %s %s %d %s %s %s", &lsec,
+                         &act, &gRSAKey, &parid, &remid, host, user,
+                         &shmid, subj, tkn, dumm);
+                  //if ((parid == getppid()) && (remid == RemId)
+                  if ((remid == RemId)
+                      && !strcmp(host, Host) && !strcmp(subj, User)) {
+                     GoodOfs = 1;
+                     goto found;
+                  }
+               } else {
+                  //if ((parid == getppid()) && (remid == RemId) &&
+                  if ((remid == RemId) &&
+                      !strcmp(host, Host) && !strcmp(user, User)) {
+                     GoodOfs = 1;
+                     goto found;
+                  }
+               }
+            }
+         }
+      }
+   }
+
+ found:
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckAuthTab: GoodOfs: %d", GoodOfs);
+
+   // Rename the key file, if needed
+   if (*OffSet > 0 && *OffSet != ofs) {
+      char *OldName = new char[strlen(gTmpDir) + 50];
+      char *NewName = new char[strlen(gTmpDir) + 50];
+      //sprintf(OldName, "%s/rpk_%d_%d", gTmpDir, getppid(), *OffSet);
+      //sprintf(NewName, "%s/rpk_%d_%d", gTmpDir, getppid(), ofs);
+      sprintf(OldName, "%s/rpk_%d", gTmpDir, *OffSet);
+      sprintf(NewName, "%s/rpk_%d", gTmpDir, ofs);
+      if (rename(OldName, NewName) == -1) {
+         if (gDebug > 0)
+            ErrorInfo
+                ("RpdCheckAuthTab: Error renaming public key file (errno: %d)",
+                 GetErrno());
+         fseek(ftab, ofs, SEEK_SET);
+         // set entry inactive
+         if (Sec == 3) {
+#ifdef R__GLBS
+            // kGlobus:
+            sprintf(line, "%d %d %d %d %d %s %s %d %s %s\n", lsec, 0,
+                    gRSAKey, parid, remid, host, user, shmid, subj,
+                    tkn);
+#else
+            ErrorInfo
+                ("RpdCheckAuthTab: compiled without Globus support: you shouldn't have got here!");
+#endif
+         } else {
+            sprintf(line, "%d %d %d %d %d %s %s %s\n", lsec, 0, gRSAKey,
+                    parid, remid, host, user, tkn);
+         }
+         while (write(itab, line, strlen(line)) < 0
+                && GetErrno() == EINTR)
+            ResetErrno();
+      }
+      SafeDelete(OldName);
+      SafeDelete(NewName);
+   }
+
+   // Receive Token
+   char *token = 0;
+   if (gRSAKey > 0) {
+      // Get Public Key
+      char PubKeyFile[kMAXPATHLEN];
+      sprintf(PubKeyFile, "%s/rpk_%d", gTmpDir, ofs);
+      if (gDebug > 2)
+         ErrorInfo("RpdCheckAuthTab: RSAKey ofs file: %d %d '%s' ",
+                   gRSAKey, ofs, PubKeyFile);
+      if (RpdGetRSAKeys(PubKeyFile, 1) > 0) {
+         if (RpdSecureRecv(&token) == -1) {
+            ErrorInfo
+                ("RpdCheckAuthTab: problems secure-receiving token - may result in authentication failure ");
+         }
+      }
+   } else {
+      EMessageTypes kind;
+      int Tlen = 9;
+      token = new char[Tlen];
+      NetRecv(token, Tlen, kind);
+      if (kind != kMESS_STRING)
+         ErrorInfo
+             ("RpdCheckAuthTab: got msg kind: %d instead of %d (kMESS_STRING)",
+              kind, kMESS_STRING);
+      // Invert Token
+      for (int i = 0; i < (int) strlen(token); i++) {
+         token[i] = ~token[i];
+      }
+   }
+
+   if (gDebug > 2)
+      ErrorInfo
+          ("RpdCheckAuthTab: received from client: token: '%s' ",
+           token);
+
+   // Now check Token validity
+   if (GoodOfs && (act == 1) && token && RpdCheckToken(token, tkn)) {
+
+      if (Sec == 3) {
+#ifdef R__GLBS
+         // kGlobus:
+         if (GlbsToolCheckContext(shmid)) {
+            retval = 1;
+            strcpy(gUser, user);
+         } else {
+            // set entry inactive
+            fseek(ftab, ofs, SEEK_SET);
+            sprintf(line, "%d %d %d %d %d %s %s %d %s %s\n", lsec, 0,
+                    gRSAKey, parid, remid, host, user, shmid, subj,
+                    tkn);
+            while (write(itab, line, strlen(line)) < 0
+                   && GetErrno() == EINTR)
+               ResetErrno();
+         }
+#else
+         ErrorInfo
+                ("RpdCheckAuthTab: compiled without Globus support: you shouldn't have got here!");
+#endif
+      } else {
+            retval = 1;
+      }
+
+      // Comunicate new offset to remote client
+      if (retval) *OffSet = ofs;
+   }
+
+   // unlock the file
+   lseek(itab, 0, SEEK_SET);
+   if (lockf(itab, F_ULOCK, (off_t) 1) == -1) {
+      ErrorInfo("RpdCheckAuthTab: error unlocking %s", gRpdAuthTab);
+   }
+   // closing file ...
+   close(itab);
+
+   return retval;
+}
+
+//______________________________________________________________________________
+bool RpdCheckToken(char *token, char *tknref)
+{
+   // Check token validity.
+
+   // Get rid of '\n'
+   char *s = strchr(token, '\n');
+   if (s)
+      *s = 0;
+   s = strchr(tknref, '\n');
+   if (s)
+      *s = 0;
+
+   char *tkn_crypt = crypt(token, tknref);
+
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckToken: ref:'%s' crypt:'%s'", tknref, tkn_crypt);
+
+   if (!strncmp(tkn_crypt, tknref, 13))
+      return 1;
+   else
+      return 0;
+}
+
+//______________________________________________________________________________
+bool RpdReUseAuth(const char *sstr, int kind)
+{
+   // Check the requiring subject has already authenticated during this session
+   // and its 'ticket' is still valid.
+   // Not implemented for SRP and Krb5 (yet).
+
+   int Ulen, OffSet, Opt;
+   gOffSet = -1;
+   gAuth = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdReUseAuth: analyzing: %s, %d", sstr, kind);
+
+   char *User = new char[strlen(sstr)];
+   char *Token = 0;
+
+   // kClear
+   if (kind == kROOTD_USER) {
+      if (!(gReUseAllow & kAUTH_CLR_MSK))
+         return 0;              // re-authentication required by administrator
+      gSec = 0;
+      // Decode subject string
+      sscanf(sstr, "%d %d %d %d %s", &gRemPid, &OffSet, &Opt, &Ulen, User);
+      User[Ulen] = '\0';
+      if ((gReUseRequired = (Opt & kAUTH_REUSE_MSK))) {
+         gOffSet = OffSet;
+         if (gRemPid > 0 && gOffSet > -1) {
+            gAuth =
+                RpdCheckAuthTab(gSec, User, gOpenHost, gRemPid, &gOffSet);
+         }
+         if ((gAuth == 1) && (OffSet != gOffSet))
+            gAuth = 2;
+         // Fill gUser and free allocated memory
+         strcpy(gUser, User);
+      }
+   }
+   // kSRP
+   if (kind == kROOTD_SRPUSER) {
+      if (!(gReUseAllow & kAUTH_SRP_MSK))
+         return 0;              // re-authentication required by administrator
+      gSec = 1;
+      // Decode subject string
+      sscanf(sstr, "%d %d %d %d %s", &gRemPid, &OffSet, &Opt, &Ulen, User);
+      User[Ulen] = '\0';
+      if ((gReUseRequired = (Opt & kAUTH_REUSE_MSK))) {
+         gOffSet = OffSet;
+         if (gRemPid > 0 && gOffSet > -1) {
+            gAuth =
+                RpdCheckAuthTab(gSec, User, gOpenHost, gRemPid, &gOffSet);
+         }
+         if ((gAuth == 1) && (OffSet != gOffSet))
+            gAuth = 2;
+         // Fill gUser and free allocated memory
+         strcpy(gUser, User);
+      }
+   }
+   // kKrb5
+   if (kind == kROOTD_KRB5) {
+      if (!(gReUseAllow & kAUTH_KRB_MSK))
+         return 0;              // re-authentication required by administrator
+      gSec = 2;
+      // Decode subject string
+      sscanf(sstr, "%d %d %d %d %s", &gRemPid, &OffSet, &Opt, &Ulen, User);
+      User[Ulen] = '\0';
+      if ((gReUseRequired = (Opt & kAUTH_REUSE_MSK))) {
+         gOffSet = OffSet;
+         if (gRemPid > 0 && gOffSet > -1) {
+            gAuth =
+                RpdCheckAuthTab(gSec, User, gOpenHost, gRemPid, &gOffSet);
+         }
+         if ((gAuth == 1) && (OffSet != gOffSet))
+            gAuth = 2;
+         // Fill gUser and free allocated memory
+         strcpy(gUser, User);
+      }
+   }
+   // kGlobus
+   if (kind == kROOTD_GLOBUS) {
+      if (!(gReUseAllow & kAUTH_GLB_MSK))
+         return 0;              //  re-authentication required by administrator
+      gSec = 3;
+      // Decode subject string
+      int Slen;
+      sscanf(sstr, "%d %d %d %d %s", &gRemPid, &OffSet, &Opt, &Slen, User);
+      User[Slen] = '\0';
+      if ((gReUseRequired = (Opt & kAUTH_REUSE_MSK))) {
+         gOffSet = OffSet;
+         if (gRemPid > 0 && gOffSet > -1) {
+            gAuth =
+                RpdCheckAuthTab(gSec, User, gOpenHost, gRemPid, &gOffSet);
+         }
+         if ((gAuth == 1) && (OffSet != gOffSet))
+            gAuth = 2;
+      }
+   }
+   // kSSH
+   if (kind == kROOTD_SSH) {
+      if (!(gReUseAllow & kAUTH_SSH_MSK))
+         return 0;              //  re-authentication required by administrator
+      gSec = 4;
+      // Decode subject string
+      char *Pipe = new char[strlen(sstr)];
+      sscanf(sstr, "%d %d %d %s %d %s", &gRemPid, &OffSet, &Opt, Pipe,
+             &Ulen, User);
+      User[Ulen] = '\0';
+      if ((gReUseRequired = (Opt & kAUTH_REUSE_MSK))) {
+         gOffSet = OffSet;
+         if (gRemPid > 0 && gOffSet > -1) {
+            gAuth =
+                RpdCheckAuthTab(gSec, User, gOpenHost, gRemPid, &gOffSet);
+         }
+         if ((gAuth == 1) && (OffSet != gOffSet))
+            gAuth = 2;
+         // Fill gUser and free allocated memory
+         strcpy(gUser, User);
+      }
+      SafeDelete(Pipe);
+   }
+
+   SafeDelete(User);
+   SafeDelete(Token);
+
+   // Return value
+   if (gAuth >= 1) {
+      return 1;
+   } else {
+      return 0;
+   }
+}
+
+//______________________________________________________________________________
+int RpdCheckAuthAllow(int Sec, char *Host)
+{
+   // Check if required auth method is allowed for 'Host'.
+   // If 'yes', returns 0,
+   // if 'no', returns 1, the number of allowed methods in NumAllow, and the
+   // codes of the allowed methods (in order of preference) in AllowMeth.
+   // Memory for AllowMeth must be allocated outside.
+   // Info read from /etc/root/rpdauth.allow.
+
+   int retval = 1, found = 0;
+
+   if (gDebug > 2)
+      ErrorInfo
+          ("RpdCheckAuthAllow: Checking file: %s for meth:%d host:%s (gNumAllow: %d)",
+           gAuthAllow, Sec, Host, gNumAllow);
+
+   // Check if info already loaded (not first call ...)
+   if (gMethInit == 1) {
+
+      // Look for the method in the allowed list and flag this method as tried, if found ...
+      int newtry = 0, i;
+      for (i = 0; i < gNumAllow; i++) {
+         if (gTriedMeth[i] == 0 && gAllowMeth[i] == Sec) {
+            newtry = 1;
+            gTriedMeth[i] = 1;
+            gNumLeft--;
+         }
+      }
+      if (newtry == 0) {
+         ErrorInfo
+             ("RpdCheckAuthAllow: new auth method proposed by client not in the list or already attempted");
+         return retval;
+      }
+      retval = 0;
+
+   } else {
+      // This is the first call ... check for host specific directives
+      gMethInit = 1;
+
+      // First check if file exists and can be read
+      if (access(gAuthAllow, F_OK))
+         return retval;
+      if (access(gAuthAllow, R_OK)) {
+         ErrorInfo("RpdCheckAuthAllow: can't read file %s (errno: %d)",
+                   gAuthAllow, GetErrno());
+         return retval;
+      }
+      // Open file
+      FILE *ftab = fopen(gAuthAllow, "r");
+      if (ftab == 0) {
+         ErrorInfo("RpdCheckAuthAllow: error opening %s (errno: %d)",
+                   gAuthAllow, GetErrno());
+         return retval;
+      }
+      // Get IP of the host in form of a string
+      char *IP = RpdGetIP(Host);
+      if (gDebug > 2)
+         ErrorInfo("RpdCheckAuthAllow: Host: %s --> IP: %s", Host, IP);
+
+      // Now read the entry
+      char line[kMAXPATHLEN], host[kMAXPATHLEN], rest[kMAXPATHLEN],
+          cmth[kMAXPATHLEN];
+      int nmet = 0, mth[6] = { 0 };
+
+      int cont = 0, jm = -1;
+      while (fgets(line, sizeof(line), ftab)) {
+         int rc = 0, i;
+         if (line[0] == '#')
+            continue;           // skip comment lines
+         if (line[strlen(line) - 1] == '\n')
+            line[strlen(line) - 1] = '\0';   // get rid of '\n', if any ...
+         // Analyze the line now ...
+         int nw = 0;
+         char *pstr = line;
+         // Check if a continuation line
+         if (cont == 1) {
+            cont = 0;
+            nw = sscanf(pstr, "%s", rest);
+            if (nw == 0)
+               continue;        // empty line
+         } else {
+            jm = -1;
+            // Get 'host' first ...
+            nw = sscanf(pstr, "%s %s", host, rest);
+            if (nw < 2)
+               continue;        // no method defined for this host
+            //         pstr = strstr(line,rest);
+            pstr = line + strlen(host) + 1;
+            if (gDebug > 2)
+               ErrorInfo("RpdCheckAuthAllow: found host: %s ", host);
+
+            if (strcmp(host, "default")) {
+               // now check validity of 'host' format
+               // Try first to understand whether it is an address or a name ...
+               int name = 0, namew = 0, nd = 0, nn = 0, nnmx = 0, nnmi =
+                   strlen(host);
+               for (i = 0; i < (int) strlen(host); i++) {
+                  if (host[i] == '.') {
+                     nd++;
+                     if (nn > nnmx)
+                        nnmx = nn;
+                     if (nn < nnmi)
+                        nnmi = nn;
+                     nn = 0;
+                     continue;
+                  }
+                  int j = (int) host[i];
+                  if (j < 48 | j > 57)
+                     name = 1;
+                  if (host[i] == '*') {
+                     namew = 1;
+                     if (nd > 0)
+                        goto next;
+                  }
+                  nn++;
+               }
+               // Act accordingly ...
+               if (name == 0) {
+                  if (nd < 4) {
+                     if (strlen(host) < 16) {
+                        if (nnmx < 4) {
+                           if (nd == 3 || host[strlen(host) - 1] == '.') {
+                              char *sp = strstr(IP, host);
+                              if (sp == 0 || sp != IP)
+                                 goto next;
+
+                           }
+                        }
+                     }
+                  }
+               } else {
+                  if (namew == 0) {
+                     if (nd > 0) {
+                        if (nd > 1 || nnmi > 0) {
+                           char *sp = strstr(Host, host);
+                           if (sp == 0 || sp != Host)
+                              goto next;
+                        }
+                     }
+                  } else {
+                     if (RpdCheckHostWild(Host, host))
+                        goto next;
+                  }
+               }
+            } else {
+               // This is a default entry: ignore it if a host-specific entry was already
+               // found, analyse it otherwise ...
+               if (found == 1)
+                  goto next;
+            }
+
+            if (rc != 0)
+               continue;        // bad or unmatched name
+
+            // Reset mth[kMAXSEC]
+            nmet = 0;
+            for (i = 0; i < kMAXSEC; i++) {
+               mth[i] = -1;
+            }
+
+         }
+
+         // We are at the end and there will be a continuation line ...
+         if ((int) rest[0] == 92) {
+            cont = 1;
+            continue;
+         }
+
+         while (pstr != 0) {
+            int tmet = -1;
+            char *pd = 0, *pd2 = 0;
+            cmth[0] = '\0';
+            rest[0] = '\0';
+            nw = sscanf(pstr, "%s %s", cmth, rest);
+            if (!strcmp(cmth, "none")) {
+               nmet = 0;
+               goto nexti;
+            }
+            pd = strchr(cmth, ':');
+            // Parse the method
+            char tmp[20];
+            if (pd != 0) {
+               int mlen = pd - cmth;
+               strncpy(tmp, cmth, mlen);
+               tmp[mlen] = '\0';
+            } else {
+               strcpy(tmp, cmth);
+            }
+            if (strlen(tmp) > 1) {
+               // Method passed as string: translate it to number
+               char *pmet = strstr(kMethods, tmp);
+               if (pmet != 0) {
+                  tmet = ((int) (pmet - kMethods)) / 7;
+               } else {
+                  ErrorInfo
+                      ("RpdCheckAuthAllow: unknown methods %s - ignore",
+                       tmp);
+                  goto nexti;
+               }
+            } else {
+               tmet = atoi(tmp);
+            }
+            jm = -1;
+            if (gDebug > 2)
+               ErrorInfo("RpdCheckAuthAllow: found method %d (have?:%d)",
+                         tmet, gHaveMeth[tmet]);
+            if (tmet >= 0 && tmet <= kMAXSEC) {
+               if (gHaveMeth[tmet] == 1) {
+                  int i;
+                  for (i = 0; i < nmet; i++) {
+                     if (mth[i] == tmet) {
+                        jm = i;
+                     }
+                  }
+               } else
+                  goto nexti;
+            } else
+               goto nexti;
+            if (jm == -1) {
+               // New method ...
+               mth[nmet] = tmet;
+               jm = nmet;
+               nmet++;
+            }
+            // Now parse users list, if any ...
+            while (pd != 0 && (int) (pd[1]) != 32) {
+               pd2 = strchr(pd + 1, ':');
+               if (pd[1] == '-') {
+                  pd += 2;
+                  // Ignore
+                  if (gUserIgnore[mth[jm]] == 0) {
+                     gUserIgnLen[mth[jm]] = kMAXPATHLEN;
+                     gUserIgnore[mth[jm]] = new char[gUserIgnLen[mth[jm]]];
+                     gUserIgnore[mth[jm]][0] = '\0';
+                  }
+                  if (strlen(gUserIgnore[mth[jm]]) >
+                      (gUserIgnLen[mth[jm]] - 10)) {
+                     char *UItmp = strdup(gUserIgnore[mth[jm]]);
+                     free(gUserIgnore[mth[jm]]);
+                     gUserIgnLen[mth[jm]] += kMAXPATHLEN;
+                     gUserIgnore[mth[jm]] = new char[gUserIgnLen[mth[jm]]];
+                     strcpy(gUserIgnore[mth[jm]], UItmp);
+                     free(UItmp);
+                  }
+                  char usr[256];
+                  if (pd2 != 0) {
+                     int ulen = pd2 - pd;
+                     strncpy(usr, pd, ulen);
+                     usr[ulen] = '\0';
+                  } else {
+                     strcpy(usr, pd);
+                  }
+                  struct passwd *pw = getpwnam(usr);
+                  if (pw != 0)
+                     sprintf(gUserIgnore[mth[jm]], "%s %d",
+                             gUserIgnore[mth[jm]], pw->pw_uid);
+               } else {
+                  pd += 1;
+                  if (pd[1] == '+')
+                     pd += 1;
+                  // Keep
+                  if (gUserAllow[mth[jm]] == 0) {
+                     gUserAlwLen[mth[jm]] = kMAXPATHLEN;
+                     gUserAllow[mth[jm]] = new char[gUserAlwLen[mth[jm]]];
+                     gUserAllow[mth[jm]][0] = '\0';
+                  }
+                  if (strlen(gUserAllow[mth[jm]]) >
+                      (gUserAlwLen[mth[jm]] - 10)) {
+                     char *UItmp = strdup(gUserAllow[mth[jm]]);
+                     free(gUserAllow[mth[jm]]);
+                     gUserAlwLen[mth[jm]] += kMAXPATHLEN;
+                     gUserAllow[mth[jm]] = new char[gUserAlwLen[mth[jm]]];
+                     strcpy(gUserAllow[mth[jm]], UItmp);
+                     free(UItmp);
+                  }
+                  char usr[256];
+                  if (pd2 != 0) {
+                     int ulen = pd2 - pd;
+                     strncpy(usr, pd, ulen);
+                     usr[ulen] = '\0';
+                  } else {
+                     strcpy(usr, pd);
+                  }
+                  struct passwd *pw = getpwnam(usr);
+                  if (pw != 0)
+                     sprintf(gUserAllow[mth[jm]], "%s %d",
+                             gUserAllow[mth[jm]], pw->pw_uid);
+               }
+               pd = pd2;
+            }
+            // Get next item
+          nexti:
+            if (nw > 1 && (int) rest[0] != 92) {
+               pstr = strstr(pstr, rest);
+            } else {
+               if ((int) rest[0] == 92)
+                  cont = 1;
+               pstr = 0;
+            }
+         }
+         if (gDebug > 2) {
+            ErrorInfo("RpdCheckAuthAllow: for host %s found %d methods",
+                      host, nmet);
+            ErrorInfo("RpdCheckAuthAllow: %d %d %d %d %d %d", mth[0],
+                      mth[1], mth[2], mth[3], mth[4], mth[5]);
+         }
+         // Found new entry matching: superseed previous result
+         found = 1;
+         retval = 1;
+         gNumAllow = gNumLeft = nmet;
+         for (i = 0; i < kMAXSEC; i++) {
+            gAllowMeth[i] = -1;
+            gTriedMeth[i] = 0;
+            if (i < gNumAllow) {
+               gAllowMeth[i] = mth[i];
+               if (Sec == mth[i]) {
+                  retval = 0;
+                  gNumLeft--;
+                  gTriedMeth[i] = 1;
+               }
+            }
+         }
+       next:
+         continue;
+      }
+
+      // closing file ...
+      fclose(ftab);
+
+      // Free allocated memory
+      SafeDelete(IP);
+
+      // Use defaults if nothing found
+      if (!found) {
+         int i;
+         for (i = 0; i < gNumAllow; i++) {
+            if (Sec == gAllowMeth[i]) {
+               retval = 0;
+               gNumLeft--;
+               gTriedMeth[i] = 1;
+            }
+         }
+
+      }
+   }
+   if (gDebug > 2) {
+      ErrorInfo
+          ("RpdCheckAuthAllow: returning: %d (gNumAllow: %d, gNumLeft:%d)",
+           retval, gNumAllow, gNumLeft);
+      int i, jm;
+      for (i = 0; i < kMAXSEC; i++) {
+         jm = gAllowMeth[i];
+         if (gUserAlwLen[jm] > 0)
+            ErrorInfo("RpdCheckAuthAllow: users allowed for method %d: %s",
+                      jm, gUserAllow[jm]);
+      }
+      for (i = 0; i < kMAXSEC; i++) {
+         jm = gAllowMeth[i];
+         if (gUserIgnLen[jm] > 0)
+            ErrorInfo("RpdCheckAuthAllow: users ignored for method %d: %s",
+                      jm, gUserIgnore[jm]);
+      }
+   }
+
+   return retval;
+}
+
+//______________________________________________________________________________
+int RpdCheckHostWild(const char *Host, const char *host)
+{
+   // Checks if 'host' is compatible with 'Host' taking into account
+   // wild cards in the machine name (first field of FQDN) ...
+   // Returns 0 if successful, 1 otherwise ...
+
+   int rc = 0;
+   char *fH, *sH, *dum, *sp, *k;
+   int i, j, lmax;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckHostWild: analyzing Host:%s host:%s", Host, host);
+
+   // Max length for dinamic allocation
+   lmax = strlen(Host) > strlen(host) ? strlen(Host) : strlen(host);
+
+   // allocate
+   fH = new char[lmax];
+   sH = new char[lmax];
+   dum = new char[lmax];
+
+   // Determine 'Host' first field (the name) ...
+   for (i = 0; i < (int) strlen(Host); i++) {
+      if (Host[i] == '.')
+         break;
+   }
+   strncpy(fH, Host, i);
+   fH[i] = '\0';
+   // ... and also the second one (the domain)
+   strcpy(sH, Host + i);
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckHostWild: fH:%s sH:%s", fH, sH);
+
+   // Now check the first field ...
+   j = 0;
+   k = fH;
+   for (i = 0; i < (int) strlen(host); i++) {
+      if (host[i] == '.')
+         break;
+      if (host[i] == '*') {
+         if (i > 0) {
+            // this is the part of name before the '*' ....
+            strncpy(dum, host + j, i - j);
+            dum[i - j] = '\0';
+            if (gDebug > 2)
+               ErrorInfo("RpdCheckHostild: k:%s dum:%s", k, dum);
+            sp = strstr(k, dum);
+            if (sp == 0) {
+               rc = 1;
+               goto exit;
+            }
+            j = i + 1;
+            k = sp + strlen(dum) + 1;
+         } else
+            j++;
+      }
+   }
+   // Now check the domain name (if the name matches ...)
+   if (rc == 0) {
+      strcpy(dum, host + i);
+      if (gDebug > 2)
+         ErrorInfo("RpdCheckHostild: sH:%s dum:%s", sH, dum);
+      sp = strstr(sH, dum);
+      if (sp == 0)
+         rc = 1;
+   }
+
+ exit:
+   // Release allocated memory ...
+   SafeDelete(fH);
+   SafeDelete(sH);
+   SafeDelete(dum);
+
+   return rc;
+}
+
+//______________________________________________________________________________
+char *RpdGetIP(const char *host)
+{
+   // Get IP address of 'host' as a string. String must be deleted by
+   // the user.
+
+   struct hostent *h;
+   unsigned long ip;
+   unsigned char ip_fld[4];
+
+   // Check server name
+   if ((h = gethostbyname(host)) == 0) {
+      ErrorInfo("RpdGetIP: unknown host %s", host);
+      return 0;
+   }
+   // Decode ...
+   ip = ntohl(*(unsigned long *) h->h_addr_list[0]);
+   ip_fld[0] = (unsigned char) ((0xFF000000 & ip) >> 24);
+   ip_fld[1] = (unsigned char) ((0x00FF0000 & ip) >> 16);
+   ip_fld[2] = (unsigned char) ((0x0000FF00 & ip) >> 8);
+   ip_fld[3] = (unsigned char) ((0x000000FF & ip));
+
+   // Prepare output
+   char *output = new char[20];
+   sprintf(output, "%d.%d.%d.%d",
+           ip_fld[0], ip_fld[1], ip_fld[2], ip_fld[3]);
+
+   // return
+   return output;
+}
+
+//______________________________________________________________________________
+void RpdSendAuthList()
+{
+   // Send list of authentication methods not yet tried.
+
+   if (gDebug > 2)
+      ErrorInfo("RpdSendAuthList: analyzing (gNumLeft: %d)", gNumLeft);
+
+   // Send Number of methids left
+   NetSend(gNumLeft, kROOTD_NEGOTIA);
+
+   if (gNumLeft > 0) {
+      int i, ldum = gNumLeft * 3;
+      char *sdum = new char[ldum];
+      sdum[0] = '\0';
+      for (i = 0; i < gNumAllow; i++) {
+         if (gDebug > 2)
+            ErrorInfo("RpdSendAuthList: gTriedMeth[%d]: %d", i,
+                      gTriedMeth[i]);
+         if (gTriedMeth[i] == 0) {
+            sprintf(sdum, "%s %d", sdum, gAllowMeth[i]);
+         }
+      }
+      NetSend(sdum, ldum, kMESS_STRING);
+      if (gDebug > 2)
+         ErrorInfo("RpdSendAuthList: sent list: %s", sdum);
+      SafeDelete(sdum);
+   }
+}
+
+
+//______________________________________________________________________________
+void RpdSshAuth(const char *sstr)
+{
+   // Reset global variable.
+
+   gAuth = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdSshAuth: contacted by host: %s for user %s", gOpenHost,
+                sstr);
+
+   // Decode subject string
+   char *User = new char[strlen(sstr)], *Pipe = new char[strlen(sstr)];
+   int Ulen, ofs, opt;
+   char dumm[20];
+   sscanf(sstr, "%d %d %d %s %d %s %s", &gRemPid, &ofs, &opt, Pipe, &Ulen,
+          User, dumm);
+   User[Ulen] = '\0';
+   gReUseRequired = (opt & kAUTH_REUSE_MSK);
+
+   // Check if we have been called to notify failure ...
+   if (gRemPid < 0) {
+      if (gDebug > 2)
+         ErrorInfo
+             ("RpdSshAuth: this is a failure notification (%s,%s,%d,%s)",
+              User, gOpenHost, gRemPid, Pipe);
+      if (SshToolNotifyFailure(Pipe)) {
+         ErrorInfo
+             ("RpdSshAuth: failure notification perhaps unsuccessful ... ");
+      }
+      SafeDelete(User);
+      SafeDelete(Pipe);
+      return;
+   }
+   // Check user existence and get its environment
+   struct passwd *pw = getpwnam(User);
+   if (!pw) {
+      ErrorInfo("RpdSshAuth: entry for user % not found in /etc/passwd",
+                User);
+      NetSend(-2, kROOTD_SSH);
+      SafeDelete(User);
+      SafeDelete(Pipe);
+      return;
+   }
+   // Method cannot be attempted for anonymous users ... (ie data servers )...
+   if (!strcmp(pw->pw_shell, "/bin/false")) {
+      ErrorInfo("RpdSshAuth: no SSH for anonymous user '%s' ", User);
+      NetSend(-2, kROOTD_SSH);
+      SafeDelete(User);
+      SafeDelete(Pipe);
+      return;
+   }
+
+   // Now we create an internal (UNIX) socket to listen to the result of sshd from ssh2rpd
+   // Path will be /tmp/rootdSSH_<random_string>
+   int UnixFd;
+   char *UniquePipe = new char[20];
+   if ((UnixFd =
+        SshToolAllocateSocket(pw->pw_uid, pw->pw_gid, &UniquePipe)) < 0) {
+      ErrorInfo
+          ("RpdSshAuth: can't allocate UNIX socket for authentication");
+      NetSend(0, kROOTD_SSH);
+      SafeDelete(User);
+      SafeDelete(Pipe);
+      SafeDelete(UniquePipe);
+      return;
+   }
+   // Communicate command to be executed via ssh ...
+   char *CmdInfo = new char[kMAXPATHLEN];
+   if (gRootLog == 0 && strlen(gFileLog) > 0) {
+      sprintf(CmdInfo, "%s/ssh2rpd %d %s %d %d %s", gExecDir, gDebug,
+              UniquePipe, getpid(), gRemPid, gFileLog);
+   } else {
+      sprintf(CmdInfo, "%s/ssh2rpd %d %s %d %d", gExecDir, gDebug,
+              UniquePipe, getpid(), gRemPid);
+   }
+   if (gSshdPort != 22) {
+      sprintf(CmdInfo, "%s port:%d", CmdInfo, gSshdPort);
+   }
+
+   if (gDebug > 2)
+      ErrorInfo("RpdSshAuth: sending CmdInfo (%d) %s", strlen(CmdInfo),
+                CmdInfo);
+   NetSend(strlen(CmdInfo), kROOTD_SSH);
+   NetSend(CmdInfo, strlen(CmdInfo), kROOTD_SSH);
+
+   // Wait for verdict form sshd (via ssh2rpd ...)
+   gAuth = SshToolGetAuth(UnixFd);
+
+   // Close socket
+   SshToolDiscardSocket(UniquePipe, UnixFd);
+
+   // If failure, notify and return ...
+   if (gAuth == 0) {
+      NetSend(kErrAuthNotOK, kROOTD_ERR);  // Send message length first
+      SafeDelete(User);
+      SafeDelete(Pipe);
+      SafeDelete(UniquePipe);
+      return;
+   }
+   // notify the client
+   if (gDebug > 0 && gAuth == 1)
+      ErrorInfo("RpdSshAuth: user %s authenticated by sshd", User);
+
+   // Save username ...
+   strcpy(gUser, User);
+
+   char line[kMAXPATHLEN];
+   if ((gReUseAllow & kAUTH_SSH_MSK) && gReUseRequired) {
+
+      // Ask for the RSA key
+      NetSend(1, kROOTD_RSAKEY);
+
+      EMessageTypes kind;
+      NetRecv(gPubKey, kMAXPATHLEN, kind);
+      if (gDebug > 2)
+         ErrorInfo("RpdSshAuth: got RSA key: (%d) '%s' len: %d", kind,
+                   gPubKey, strlen(gPubKey));
+
+      // Import Key and Determine key type
+      gRSAKey = RpdGetRSAKeys(gPubKey, 0);
+      if (gRSAKey == 0) {
+         ErrorInfo
+             ("RpdSshAuth: could not import a valid key - switch off reuse for this session");
+         gReUseRequired = 0;
+      }
+      // Set an entry in the auth tab file for later (re)use, if required ...
+      int OffSet = -1;
+      char *token = 0;
+      if (gReUseRequired) {
+         sprintf(line, "%d %d %d %d %d %s %s", 4, 1, gRSAKey, getppid(),
+                 gRemPid, gOpenHost, gUser);
+         OffSet = RpdUpdateAuthTab(1, line, &token);
+      }
+      // Comunicate login user name to client
+      sprintf(line, "%s %d", gUser, OffSet);
+      NetSend(strlen(line), kROOTD_SSH);   // Send message length first
+      NetSend(line, kMESS_STRING);
+
+      if (gReUseRequired) {
+         // Send over the token
+         if (RpdSecureSend(token) == -1) {
+            ErrorInfo
+                ("RpdSshAuth: problems secure-sending token - may result in corrupted token");
+         }
+         SafeDelete(token);
+
+         // Save RSA public key into file for later use by other rootd/proofd
+         RpdSavePubKey(gPubKey, OffSet);
+      }
+   } else {
+      // Comunicate login user name to client
+      sprintf(line, "%s -1", gUser);
+      NetSend(strlen(line), kROOTD_SSH);   // Send message length first
+      NetSend(line, kMESS_STRING);
+   }
+
+   // Release allocated memory
+   SafeDelete(User);
+   SafeDelete(Pipe);
+   SafeDelete(UniquePipe);
+   SafeDelete(CmdInfo);
+
+   return;
+}
+
+//______________________________________________________________________________
+void RpdKrb5Auth(const char *sstr)
+{
+   // Authenticate via Kerberos.
+
+   gAuth = 0;
+
+#ifdef R__KRB5
+   NetSend(1, kROOTD_KRB5);
+   // TAuthenticate will respond to our encouragement by sending krb5
+   // authentication through the socket
+#else
+   NetSend(0, kROOTD_KRB5);
+   return;
+#endif
+
+#ifdef R__KRB5
+   int retval;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdKrb5Auth: analyzing ... %s", sstr);
+
+   if (gClientProtocol > 8) {
+      char *User = new char[strlen(sstr)];
+      int Ulen, ofs, opt;
+      char dumm[20];
+      // Decode subject string
+      sscanf(sstr, "%d %d %d %d %s %s", &gRemPid, &ofs, &opt, &Ulen, User,
+             dumm);
+      User[Ulen] = '\0';
+      gReUseRequired = (opt & kAUTH_REUSE_MSK);
+      SafeDelete(User);
+   }
+   // get service principal
+   krb5_principal server;
+   if ((retval = krb5_sname_to_principal(gKcontext, 0, gService,
+                                         KRB5_NT_SRV_HST, &server))) {
+      ErrorInfo("RpdKrb5Auth: while generating service name (%s): %s",
+                gService, error_message(retval));
+      return;
+   }
+   // listen for authentication from the client
+   krb5_auth_context auth_context = 0;
+   krb5_ticket *ticket;
+   char proto_version[100] = "krootd_v_1";
+   int sock = gSockFd;
+   if ((retval = krb5_recvauth(gKcontext, &auth_context,
+                               (krb5_pointer) &sock, proto_version, server,
+                               0, gKeytab,   // default gKeytab is 0
+                               &ticket))) {
+      ErrorInfo("RpdKrb5Auth: recvauth failed--%s", error_message(retval));
+      return;
+   }
+   // get client name
+   char *cname;
+   if ((retval =
+        krb5_unparse_name(gKcontext, ticket->enc_part2->client, &cname))) {
+      ErrorInfo("RpdKrb5Auth: unparse failed: %s", error_message(retval));
+      return;
+   }
+
+   using std::string;
+   string user = cname;
+   free(cname);
+   string reply = "authenticated as ";
+   reply += user;
+
+   // set user name
+   user = user.erase(user.find("@"));   // cut off realm
+   string::size_type pos = user.find("/");   // see if there is an instance
+   if (pos != string::npos)
+      user = user.erase(pos);   // drop the instance
+   strncpy(gUser, user.c_str(), 64);
+
+   NetSend(reply.c_str(), kMESS_STRING);
+   krb5_auth_con_free(gKcontext, auth_context);
+
+   // Authentication was successfull
+   gAuth = 1;
+
+   if (gClientProtocol > 8) {
+
+      char line[kMAXPATHLEN];
+      if ((gReUseAllow & kAUTH_KRB_MSK) && gReUseRequired) {
+
+         // Ask for the RSA key
+         NetSend(1, kROOTD_RSAKEY);
+
+         EMessageTypes kind;
+         NetRecv(gPubKey, kMAXPATHLEN, kind);
+         if (gDebug > 2)
+            ErrorInfo("RpdKrb5Auth: got RSA key: (%d) '%s' len: %d", kind,
+                      gPubKey, strlen(gPubKey));
+
+         // Import key and determine its type
+         gRSAKey = RpdGetRSAKeys(gPubKey, 0);
+         if (gRSAKey == 0) {
+            ErrorInfo
+                ("RpdKrb5Auth: could not import a valid key - switch off reuse for this session");
+            gReUseRequired = 0;
+         }
+         // Set an entry in the auth tab file for later (re)use, if required ...
+         int OffSet = -1;
+         char *token = 0;
+         if (gReUseRequired) {
+            sprintf(line, "%d %d %d %d %d %s %s", 2, 1, gRSAKey, getppid(),
+                    gRemPid, gOpenHost, gUser);
+            OffSet = RpdUpdateAuthTab(1, line, &token);
+            if (gDebug > 2)
+               ErrorInfo("RpdKrb5Auth: line:%s OffSet:%d", line, OffSet);
+         }
+         // Comunicate login user name to client
+         sprintf(line, "%s %d", gUser, OffSet);
+         NetSend(strlen(line), kROOTD_KRB5);   // Send message length first
+         NetSend(line, kMESS_STRING);
+
+         // Send Token
+         if (gReUseRequired) {
+            if (RpdSecureSend(token) == -1) {
+               ErrorInfo
+                   ("RpdKerb5Auth: problems secure-sending token - may result in corrupted token");
+            }
+            SafeDelete(token);
+
+            // Save RSA public key into file for later use by other rootd/proofd
+            RpdSavePubKey(gPubKey, OffSet);
+         }
+
+      } else {
+
+         // Comunicate login user name to client
+         sprintf(line, "%s -1", gUser);
+         NetSend(strlen(line), kROOTD_KRB5);   // Send message length first
+         NetSend(line, kMESS_STRING);
+
+      }
+   } else {
+      NetSend(user.c_str(), kMESS_STRING);
+   }
+
+   if (gDebug > 0)
+      ErrorInfo("RpdKrb5Auth: user %s authenticated", gUser);
+
+#endif
+}
+
+//______________________________________________________________________________
+void RpdSRPUser(const char *sstr)
+{
+   // Use Secure Remote Password protocol.
+   // Check user id in $HOME/.srootdpass file.
+
+   gAuth = 0;
+
+   if (!*sstr) {
+      NetSend(kErrBadUser, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: bad user name");
+      return;
+   }
+
+   if (kSRootdPass[0]) {
+   }                            // remove compiler warning
+
+#ifdef R__SRP
+
+   char srootdpass[kMAXPATHLEN], srootdconf[kMAXPATHLEN];
+
+   // Decode subject string
+   char *user = new char[strlen(sstr) + 1];
+   if (gClientProtocol > 8) {
+      int Ulen, ofs, opt;
+      char dumm[20];
+      sscanf(sstr, "%d %d %d %d %s %s", &gRemPid, &ofs, &opt, &Ulen, user,
+             dumm);
+      user[Ulen] = '\0';
+      gReUseRequired = (opt & kAUTH_REUSE_MSK);
+   } else {
+      strcpy(user, sstr);
+   }
+
+   struct passwd *pw = getpwnam(user);
+   if (!pw) {
+      NetSend(kErrNoUser, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: user %s unknown", user);
+      return;
+   }
+   // Method cannot be attempted for anonymous users ... (ie data servers )...
+   if (!strcmp(pw->pw_shell, "/bin/false")) {
+      NetSend(kErrNotAllowed, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: no SRP for anonymous user '%s' ", user);
+      return;
+   }
+   // If server is not started as root and user is not same as the
+   // one who started rootd then authetication is not ok.
+   uid_t uid = getuid();
+   if (uid && uid != pw->pw_uid) {
+      NetSend(kErrBadUser, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: user not same as effective user of rootd");
+      return;
+   }
+
+   NetSend(gAuth, kROOTD_AUTH);
+
+   strcpy(gUser, user);
+
+   SafeDelete(user);
+
+   if (!gAltSRP) {
+      sprintf(srootdpass, "%s/%s", pw->pw_dir, kSRootdPass);
+      sprintf(srootdconf, "%s/%s.conf", pw->pw_dir, kSRootdPass);
+   } else {
+      sprintf(srootdpass, "%s", gAltSRPPass);
+      sprintf(srootdconf, "%s.conf", gAltSRPPass);
+   }
+
+   FILE *fp1 = fopen(srootdpass, "r");
+   if (!fp1) {
+      NetSend(kErrFileOpen, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: error opening %s", srootdpass);
+      return;
+   }
+   FILE *fp2 = fopen(srootdconf, "r");
+   if (!fp2) {
+      NetSend(kErrFileOpen, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: error opening %s", srootdconf);
+      if (fp1)
+         fclose(fp1);
+      return;
+   }
+
+   struct t_pw *tpw = t_openpw(fp1);
+   if (!tpw) {
+      NetSend(kErrFileOpen, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: unable to open password file %s", srootdpass);
+      fclose(fp1);
+      fclose(fp2);
+      return;
+   }
+
+   struct t_conf *tcnf = t_openconf(fp2);
+   if (!tcnf) {
+      NetSend(kErrFileOpen, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: unable to open configuration file %s",
+                srootdconf);
+      t_closepw(tpw);
+      fclose(fp1);
+      fclose(fp2);
+      return;
+   }
+#if R__SRP_1_1
+   struct t_server *ts = t_serveropen(gUser, tpw, tcnf);
+#else
+   struct t_server *ts = t_serveropenfromfiles(gUser, tpw, tcnf);
+#endif
+   if (!ts) {
+      NetSend(kErrNoUser, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: user %s not found SRP password file", gUser);
+      return;
+   }
+
+   if (tcnf)
+      t_closeconf(tcnf);
+   if (tpw)
+      t_closepw(tpw);
+   if (fp2)
+      fclose(fp2);
+   if (fp1)
+      fclose(fp1);
+
+   char hexbuf[MAXHEXPARAMLEN];
+
+   // send n to client
+   NetSend(t_tob64(hexbuf, (char *) ts->n.data, ts->n.len), kROOTD_SRPN);
+   // send g to client
+   NetSend(t_tob64(hexbuf, (char *) ts->g.data, ts->g.len), kROOTD_SRPG);
+   // send salt to client
+   NetSend(t_tob64(hexbuf, (char *) ts->s.data, ts->s.len),
+           kROOTD_SRPSALT);
+
+   struct t_num *B = t_servergenexp(ts);
+
+   // receive A from client
+   EMessageTypes kind;
+   if (NetRecv(hexbuf, MAXHEXPARAMLEN, kind) < 0) {
+      NetSend(kErrFatal, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: error receiving A from client");
+      return;
+   }
+   if (kind != kROOTD_SRPA) {
+      NetSend(kErrFatal, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: expected kROOTD_SRPA message");
+      return;
+   }
+
+   unsigned char buf[MAXPARAMLEN];
+   struct t_num A;
+   A.data = buf;
+   A.len = t_fromb64((char *) A.data, hexbuf);
+
+   // send B to client
+   NetSend(t_tob64(hexbuf, (char *) B->data, B->len), kROOTD_SRPB);
+
+   t_servergetkey(ts, &A);
+
+   // receive response from client
+   if (NetRecv(hexbuf, MAXHEXPARAMLEN, kind) < 0) {
+      NetSend(kErrFatal, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: error receiving response from client");
+      return;
+   }
+   if (kind != kROOTD_SRPRESPONSE) {
+      NetSend(kErrFatal, kROOTD_ERR);
+      ErrorInfo("RpdSRPUser: expected kROOTD_SRPRESPONSE message");
+      return;
+   }
+
+   unsigned char cbuf[20];
+   t_fromhex((char *) cbuf, hexbuf);
+
+   if (!t_serververify(ts, cbuf)) {
+
+      // authentication successful
+      if (gDebug > 0)
+         ErrorInfo("RpdSRPUser: user %s authenticated", gUser);
+      gAuth = 1;
+
+      if (gClientProtocol > 8) {
+
+         char line[kMAXPATHLEN];
+         if ((gReUseAllow & kAUTH_SRP_MSK) && gReUseRequired) {
+
+            // Ask for the RSA key
+            NetSend(1, kROOTD_RSAKEY);
+
+            NetRecv(gPubKey, kMAXPATHLEN, kind);
+            if (gDebug > 2)
+               ErrorInfo("RpdSRPAuth: got RSA key: (%d) '%s' len: %d",
+                         kind, gPubKey, strlen(gPubKey));
+
+            // Import key and determine its type
+            gRSAKey = RpdGetRSAKeys(gPubKey, 0);
+            if (gRSAKey == 0) {
+               ErrorInfo
+                   ("RpdSRPAuth: could not import a valid key - switch off reuse for this session");
+               gReUseRequired = 0;
+            }
+
+            // Set an entry in the auth tab file for later (re)use, if required ...
+            int OffSet = -1;
+            char *token = 0;
+            if (gReUseRequired) {
+               sprintf(line, "%d %d %d %d %d %s %s", 1, 1, gRSAKey,
+                       getppid(), gRemPid, gOpenHost, gUser);
+               OffSet = RpdUpdateAuthTab(1, line, &token);
+            }
+            // Comunicate login user name to client
+            sprintf(line, "%s %d", gUser, OffSet);
+            NetSend(strlen(line), kROOTD_SRPUSER);   // Send message length first
+            NetSend(line, kMESS_STRING);
+
+            if (gReUseRequired) {
+               // Send Token
+               if (RpdSecureSend(token) == -1) {
+                  ErrorInfo
+                      ("RpdKrb5Auth: problems secure-sending token - may result in corrupted token");
+               }
+               SafeDelete(token);
+
+               // Save RSA public key into file for later use by other rootd/proofd
+               RpdSavePubKey(gPubKey, OffSet);
+            }
+
+         } else {
+            // Comunicate login user name to client
+            sprintf(line, "%s -1", gUser);
+            NetSend(strlen(line), kROOTD_SRPUSER);   // Send message length first
+            NetSend(line, kMESS_STRING);
+         }
+
+      }
+
+   } else {
+      if (gClientProtocol > 8) {
+         NetSend(kErrBadPasswd, kROOTD_ERR);
+         ErrorInfo("RpdSRPUser: authentication failed for user %s", gUser);
+         return;
+      }
+   }
+
+   t_serverclose(ts);
+
+#else
+   NetSend(0, kROOTD_SRPUSER);
+#endif
+}
+
+//______________________________________________________________________________
+int RpdCheckSpecialPass(const char *passwd)
+{
+   // Check user's password against password in $HOME/.rootdpass. If matches
+   // skip other authentication mechanism. Returns 1 in case of success
+   // authentication, 0 otherwise.
+
+   char rootdpass[kMAXPATHLEN];
+
+   struct passwd *pw = getpwnam(gUser);
+
+   sprintf(rootdpass, "%s/%s", pw->pw_dir, kRootdPass);
+
+   int fid = open(rootdpass, O_RDONLY);
+   if (fid == -1)
+      return 0;
+
+   int n;
+   if ((n = read(fid, rootdpass, sizeof(rootdpass) - 1)) <= 0) {
+      close(fid);
+      return 0;
+   }
+   close(fid);
+
+   rootdpass[n] = 0;
+   char *s = strchr(rootdpass, '\n');
+   if (s)
+      *s = 0;
+
+   n = strlen(rootdpass);
+
+   if (strncmp(passwd, rootdpass, n + 1) != 0)
+      return 0;
+
+   if (gDebug > 0)
+      ErrorInfo
+          ("RpdCheckSpecialPass: user %s authenticated via ~/.rootdpass",
+           gUser);
+
+   return 1;
+}
+
+//______________________________________________________________________________
+void RpdPass(const char *pass)
+{
+   // Check user's password.
+
+   char passwd[64];
+   char *passw;
+   char *pass_crypt;
+   struct passwd *pw;
+#ifdef R__SHADOWPW
+   struct spwd *spw;
+#endif
+#ifdef R__AFS
+   char *reason;
+   int afs_auth = 0;
+#endif
+
+   if (gDebug > 2)
+      ErrorInfo("RpdPass: Enter");
+
+   gAuth = 0;
+   if (!*gUser) {
+      NetSend(kErrFatal, kROOTD_ERR);
+      ErrorInfo("RpdPass: user needs to be specified first");
+      return;
+   }
+
+   int n = strlen(pass);
+   // Passwd length should be in the correct range ...
+   if (!n) {
+      NetSend(kErrBadPasswd, kROOTD_ERR);
+      ErrorInfo("RpdPass: null passwd not allowed");
+      return;
+   }
+   if (n > (int) sizeof(passwd)) {
+      NetSend(kErrBadPasswd, kROOTD_ERR);
+      ErrorInfo("RpdPass: passwd too long");
+      return;
+   }
+   // Inversion is done in RpdUser, if needed
+   strcpy(passwd, pass);
+
+   // Special treatment for anonimous ...
+   if (gAnon) {
+      strcpy(gPasswd, passwd);
+      goto authok;
+   }
+   // ... and SpecialPass ...
+   if (RpdCheckSpecialPass(passwd)) {
+      goto authok;
+   }
+   // Get local passwd info for gUser
+   pw = getpwnam(gUser);
+
+#ifdef R__AFS
+   afs_auth = !ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
+                                          gUser,        //user name
+                                          (char *) 0,   //instance
+                                          (char *) 0,   //realm
+                                          passwd,       //password
+                                          0,            //default lifetime
+                                          0, 0,         //two spares
+                                          &reason);     //error string
+
+   if (!afs_auth) {
+      ErrorInfo("RpdPass: AFS login failed for user %s: %s", gUser,
+                reason);
+      // try conventional login...
+#endif
+
+#ifdef R__SHADOWPW
+      // System V Rel 4 style shadow passwords
+      if ((spw = getspnam(gUser)) == 0) {
+         ErrorInfo("RpdPass: Shadow passwd not available for user %s",
+                   gUser);
+         passw = pw->pw_passwd;
+      } else
+         passw = spw->sp_pwdp;
+#else
+      passw = pw->pw_passwd;
+#endif
+      //   if (gClientProtocol <= 8 || !gReUseRequired) {
+      if (gClientProtocol <= 8 || !gCryptRequired) {
+         pass_crypt = crypt(passwd, passw);   // Comment this
+      } else {
+         pass_crypt = passwd;
+      }
+      n = strlen(passw);
+
+      if (strncmp(pass_crypt, passw, n + 1) != 0) {
+         NetSend(kErrBadPasswd, kROOTD_ERR);
+         ErrorInfo("RpdPass: invalid password for user %s", gUser);
+         return;
+      }
+#ifdef R__AFS
+   }                            // afs_auth
+#endif
+
+ authok:
+   gAuth = 1;
+
+   if (gClientProtocol > 8) {
+      // Set an entry in the auth tab file for later (re)use, if required ...
+      int OffSet = -1;
+      char *token = 0;
+      char line[kMAXPATHLEN];
+      if ((gReUseAllow & kAUTH_CLR_MSK) && gReUseRequired) {
+
+         sprintf(line, "%d %d %d %d %d %s %s", 0, 1, gRSAKey, getppid(),
+                 gRemPid, gOpenHost, gUser);
+         OffSet = RpdUpdateAuthTab(1, line, &token);
+         if (gDebug > 2)
+            ErrorInfo("RpdPass: got offset %d", OffSet);
+
+         // Comunicate login user name to client
+         sprintf(line, "%s %d", gUser, OffSet);
+         if (gDebug > 2)
+            ErrorInfo("RpdPass: sending back line %s", line);
+         NetSend(strlen(line), kROOTD_PASS);   // Send message length first
+         NetSend(line, kMESS_STRING);
+
+         if (gDebug > 2)
+            ErrorInfo("RpdPass: sending token %s (Crypt: %d)", token,
+                      gCryptRequired);
+         if (gCryptRequired) {
+            // Send over the token
+            if (RpdSecureSend(token) == -1) {
+               ErrorInfo
+                   ("RpdPass: problems secure-sending token - may result in corrupted token");
+            }
+         } else {
+            // Send token inverted
+            for (int i = 0; i < (int) strlen(token); i++) {
+               token[i] = ~token[i];
+            }
+            NetSend(token, kMESS_STRING);
+         }
+         SafeDelete(token);
+
+      } else {
+         // Comunicate login user name to client
+         sprintf(line, "%s -1", gUser);
+         if (gDebug > 2)
+            ErrorInfo("RpdPass: sending back line %s", line);
+         NetSend(strlen(line), kROOTD_PASS);   // Send message length first
+         NetSend(line, kMESS_STRING);
+      }
+
+      if (gCryptRequired) {
+         // Save RSA public key into file for later use by other rootd/proofd
+         RpdSavePubKey(gPubKey, OffSet);
+      }
+   }
+}
+
+//______________________________________________________________________________
+void RpdGlobusAuth(const char *sstr)
+{
+   // Authenticate via Globus.
+
+   gAuth = 0;
+
+#ifndef R__GLBS
+
+   if (sstr) { }  // use sstr
+   NetSend(0, kROOTD_GLOBUS);
+   return;
+
+#else
+
+   OM_uint32 MajStat = 0;
+   OM_uint32 MinStat = 0;
+   OM_uint32 GssRetFlags = 0;
+   gss_ctx_id_t GlbContextHandle = GSS_C_NO_CONTEXT;
+   gss_cred_id_t GlbCredHandle = GSS_C_NO_CREDENTIAL;
+   gss_cred_id_t GlbDelCredHandle = GSS_C_NO_CREDENTIAL;
+   int GlbTokenStatus = 0;
+   char *GlbClientName;
+   FILE *FILE_SockFd;
+   char *gridmap_default = "/etc/grid-security/grid-mapfile";
+   EMessageTypes kind;
+   int lSubj, OffSet = -1;
+   char *user = 0;
+   int ulen = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdGlobusAuth: contacted by host: %s", gOpenHost);
+
+   // Tell the remote client that we may accept Globus credentials ...
+   NetSend(1, kROOTD_GLOBUS);
+
+   // Decode subject string
+   char *Subj = new char[strlen(sstr) + 1];
+   int opt;
+   char dumm[20];
+   sscanf(sstr, "%d %d %d %d %s %s", &gRemPid, &OffSet, &opt, &lSubj, Subj,
+          dumm);
+   Subj[lSubj] = '\0';
+   gReUseRequired = (opt & kAUTH_REUSE_MSK);
+   if (gDebug > 2)
+      ErrorInfo("RpdGlobusAuth: gRemPid: %d, Subj: %s (%d %d)", gRemPid,
+                Subj, lSubj, strlen(Subj));
+   SafeDelete(Subj);            // GlbClientName will be determined from the security context ...
+
+   // Now wait for client to communicate the issuer name of the certificate ...
+   char *answer = new char[20];
+   NetRecv(answer, (int) sizeof(answer), kind);
+   if (kind != kMESS_STRING) {
+      Error(gErr, kErrAuthNotOK,
+            "RpdGlobusAuth: client_issuer_name:received unexpected type of message (%d)",
+            kind);
+      return;
+   }
+   int client_issuer_name_len = atoi(answer);
+   SafeDelete(answer);
+   char *client_issuer_name = new char[client_issuer_name_len + 1];
+   NetRecv(client_issuer_name, client_issuer_name_len, kind);
+   if (kind != kMESS_STRING) {
+      Error(gErr, kErrAuthNotOK,
+            "RpdGlobusAuth: client_issuer_name:received unexpected type of message (%d)",
+            kind);
+      return;
+   }
+   if (gDebug > 2)
+      ErrorInfo("RpdGlobusAuth: client issuer name is: %s",
+                client_issuer_name);
+
+   // Now we open the certificates and we check if we are able to autheticate the client
+   // In the affirmative case we sen our subject name to the client ...
+   char *subject_name;
+   if (GlbsToolCheckCert(client_issuer_name, &subject_name)) {
+      ErrorInfo
+          ("RpdGlobusAuth: host does not seem to have certificate for the requested CA (%s)",
+           client_issuer_name);
+      NetSend(0, kROOTD_GLOBUS);   // Notify that we did not find it
+      return;
+   } else {
+      int sjlen = strlen(subject_name) + 1;
+      subject_name[sjlen] = '\0';
+
+      int bsnd = NetSend(sjlen, kROOTD_GLOBUS);
+      if (gDebug > 2)
+         ErrorInfo("RpdGlobusAuth: sent: %d (due >=%d))", bsnd,
+                   2 * sizeof(sjlen));
+
+      bsnd = NetSend(subject_name, sjlen, kMESS_STRING);
+      if (gDebug > 2)
+         ErrorInfo("RpdGlobusAuth: sent: %d (due >=%d))", bsnd, sjlen);
+
+      free(subject_name);
+   }
+   // not needed anymore ...
+   SafeDelete(client_issuer_name);
+
+   // Inquire Globus credentials:
+   // This is looking to file X509_USER_CERT for valid a X509 cert (default
+   // /etc/grid-security/hostcert.pem) and to dir X509_CERT_DIR for trusted CAs
+   // (default /etc/grid-security/certificates).
+   if ((MajStat =
+        globus_gss_assist_acquire_cred(&MinStat, GSS_C_ACCEPT,
+                                       &GlbCredHandle)) !=
+       GSS_S_COMPLETE) {
+      GlbsToolError("RpdGlobusAuth: gss_assist_acquire_cred", MajStat,
+                    MinStat, 0);
+      if (getuid() > 0) {
+         ErrorInfo
+             ("RpdGlobusAuth: non-root: make sure you have initialized (manually) your proxies");
+      }
+      return;
+   }
+   // We need to associate a FILE* stream with the socket
+   // It will automatically closed when the socket will be closed ...
+   FILE_SockFd = fdopen(gSockFd, "w+");
+
+   // Now we are ready to start negotiating with the Client
+   if ((MajStat =
+        globus_gss_assist_accept_sec_context(&MinStat, &GlbContextHandle,
+                                             GlbCredHandle, &GlbClientName,
+                                             &GssRetFlags, 0,
+                                             &GlbTokenStatus,
+                                             &GlbDelCredHandle,
+                                             globus_gss_assist_token_get_fd,
+                                             (void *) FILE_SockFd,
+                                             globus_gss_assist_token_send_fd,
+                                             (void *) FILE_SockFd)) !=
+       GSS_S_COMPLETE) {
+      GlbsToolError("RpdGlobusAuth: gss_assist_accept_sec_context",
+                    MajStat, MinStat, GlbTokenStatus);
+      return;
+   } else {
+      gAuth = 1;
+      if (gDebug > 0)
+         ErrorInfo("RpdGlobusAuth: user: %s \n authenticated",
+                   GlbClientName);
+   }
+
+   // If we are master we need to autheticate the slaves ...
+   if (gGlobus == 1) {          // There might be the need of credentials ...
+      // Check that we got delegation to autheticate the slaves
+      if (GssRetFlags | GSS_C_DELEG_FLAG) {
+         if (gDebug > 2)
+            ErrorInfo("RpdGlobusAuth: Pointer to del cred is 0x%x",
+                      (int) GlbDelCredHandle);
+      } else {
+         Error(gErr, kErrAuthNotOK,
+               "RpdGlobusAuth: did not get delegated credentials (RetFlags: 0x%x)",
+               GssRetFlags);
+         return;
+      }
+      // Now we have to export these delegated credentials to a shared memory segment
+      // for later use in 'proofserv' ...
+      //   credential= (gss_buffer_t)malloc(sizeof(gss_buffer_desc));
+      gss_buffer_t credential = new gss_buffer_desc;
+      if ((MajStat =
+           gss_export_cred(&MinStat, GlbDelCredHandle, 0, 0,
+                           credential)) != GSS_S_COMPLETE) {
+         GlbsToolError("RpdGlobusAuth: gss_export_cred", MajStat, MinStat,
+                       0);
+         return;
+      } else if (gDebug > 2)
+         ErrorInfo("RpdGlobusAuth: credentials prepared for export");
+
+      // Now store it in shm for later use in proofserv ...
+      int rc;
+      if ((rc = GlbsToolStoreToShm(credential, &gShmIdCred))) {
+         ErrorInfo
+             ("RpdGlobusAuth: credentials not correctly stored in shm (rc: %d)",
+              rc);
+      }
+      if (gDebug > 2)
+         ErrorInfo
+             ("RpdGlobusAuth: credentials stored in shared memory segment %d",
+              gShmIdCred);
+
+      delete credential;
+   }
+   // For Now we set the gUser to the certificate owner using the gridmap file ...
+   // Should be understood if this is really necessary ...
+   if (getenv("GRIDMAP") == 0) {
+      // The installation did not specify a special location for the gridmap file
+      // We assume the usual default ...
+      setenv("GRIDMAP", gridmap_default, 1);
+      if (gDebug > 2)
+         ErrorInfo("RpdGlobusAuth: gridmap: using default file (%s)",
+                   gridmap_default);
+   } else if (gDebug > 2)
+      ErrorInfo("RpdGlobusAuth: gridmap: using file %s",
+                getenv("GRIDMAP"));
+
+   // Get local login name for the subject ...
+   if (globus_gss_assist_gridmap(GlbClientName, &user)) {
+      if (gDebug > 2)
+         ErrorInfo
+             ("RpdGlobusAuth: unable to get local username from gridmap: using: %s",
+              gAnonUser);
+      user = strdup(gAnonUser);
+      if (gDebug > 2)
+         ErrorInfo("RpdGlobusAuth: user ", user);
+   }
+   if (!strcmp(user, "anonymous"))
+      user = strdup(gAnonUser);
+   if (!strcmp(user, gAnonUser))
+      gAnon = 1;
+
+   // Fill gUser and free allocated memory
+   ulen = strlen(user);
+   strncpy(gUser, user, ulen + 1);
+
+   char line[kMAXPATHLEN];
+   if ((gReUseAllow & kAUTH_GLB_MSK) && gReUseRequired) {
+
+      // Ask for the RSA key
+      NetSend(1, kROOTD_RSAKEY);
+
+      NetRecv(gPubKey, kMAXPATHLEN, kind);
+      if (gDebug > 2)
+         ErrorInfo("RpdGlobusAuth: got RSA key: (%d) '%s' len: %d", kind,
+                   gPubKey, strlen(gPubKey));
+
+      // Import key and determine its type
+      gRSAKey = RpdGetRSAKeys(gPubKey, 0);
+      if (gRSAKey == 0) {
+         ErrorInfo
+             ("RpdGlobusAuth: could not import a valid key - switch off reuse for this session");
+         gReUseRequired = 0;
+      }
+      // Store security context and related info for later use ...
+      OffSet = -1;
+      char *token = 0;
+      if (gReUseRequired) {
+         int ShmId = GlbsToolStoreContext(GlbContextHandle, user);
+         if (ShmId > 0) {
+            sprintf(line, "%d %d %d %d %d %s %s %d %s", 3, 1, gRSAKey,
+                    getppid(), gRemPid, gOpenHost, user, ShmId,
+                    GlbClientName);
+            OffSet = RpdUpdateAuthTab(1, line, &token);
+         } else if (gDebug > 0)
+            ErrorInfo
+                ("RpdGlobusAuth: unable to export context to shm for later use");
+      }
+      // Comunicate login user name to client (and token)
+      sprintf(line, "%s %d", gUser, OffSet);
+      NetSend(strlen(line), kROOTD_GLOBUS);   // Send message length first
+      NetSend(line, kMESS_STRING);
+
+      if (gReUseRequired) {
+         // Send Token
+         if (RpdSecureSend(token) == -1) {
+            ErrorInfo
+                ("RpdGlobusAuth: problems secure-sending token - may result in corrupted token");
+         }
+         SafeDelete(token);
+
+         // Save RSA public key into file for later use by other rootd/proofd
+         RpdSavePubKey(gPubKey, OffSet);
+      }
+   } else {
+      // Comunicate login user name to client (and token)
+      sprintf(line, "%s %d", gUser, OffSet);
+      NetSend(strlen(line), kROOTD_GLOBUS);   // Send message length first
+      NetSend(line, kMESS_STRING);
+   }
+
+   // and free allocated memory
+   free(user);
+   free(GlbClientName);
+
+   if (gDebug > 0)
+      ErrorInfo("RpdGlobusAuth: logging as %s ", gUser);
+
+#endif
+}
+
+//______________________________________________________________________________
+void RpdRfioAuth(const char *sstr)
+{
+   // Check if user and group id specified in the request exist in the
+   // passwd file. If they do then grant access. Very insecure: to be used
+   // with care.
+
+   gAuth = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdRfioAuth: analyzing ... %s", sstr);
+
+   if (!*sstr) {
+      NetSend(kErrBadUser, kROOTD_ERR);
+      ErrorInfo("RpdRfioAuth: subject string is empty");
+      return;
+   }
+   // Decode subject string
+   unsigned int uid, gid;
+   sscanf(sstr, "%d %d", &uid, &gid);
+
+   // Now inquire passwd ...
+   struct passwd *pw;
+   if ((pw = getpwuid((uid_t) uid)) == 0) {
+      NetSend(kErrBadUser, kROOTD_ERR);
+      ErrorInfo("RpdRfioAuth: uid %d not found", uid);
+      return;
+   }
+   // Check if authorized
+   char cuid[20];
+   sprintf(cuid, "%d", uid);
+   if (gUserIgnLen[5] > 0 && strstr(gUserIgnore[5], cuid) != 0) {
+      NetSend(kErrNotAllowed, kROOTD_ERR);
+      ErrorInfo
+          ("RpdRfioAuth: user (%d,%s) not authorized to use (uid:gid) method",
+           uid, pw->pw_name);
+      return;
+   }
+   if (gUserAlwLen[5] > 0 && strstr(gUserAllow[5], cuid) == 0) {
+      NetSend(kErrNotAllowed, kROOTD_ERR);
+      ErrorInfo
+          ("RpdRfioAuth: user (%d,%s) not authorized to use (uid:gid) method",
+           uid, pw->pw_name);
+      return;
+   }
+
+   // Now check group id ...
+   if (gid != pw->pw_gid) {
+      NetSend(kErrBadUser, kROOTD_ERR);
+      ErrorInfo
+          ("RpdRfioAuth: group id does not match (remote:%d,local:%d)",
+           gid, pw->pw_gid);
+      return;
+   }
+   // Set username ....
+   strcpy(gUser, pw->pw_name);
+
+
+   // Notify, if required ...
+   if (gDebug > 0)
+      ErrorInfo("RpdRfioAuth: user %s authenticated (uid:%d, gid:%d)",
+                gUser, uid, gid);
+
+   // Set Auth flag
+   gAuth = 1;
+}
+
+//______________________________________________________________________________
+void RpdCleanup(const char *sstr)
+{
+   // Cleanup auth table.
+
+   char Host[kMAXPATHLEN] = { 0 };
+   int rPid;
+
+   sscanf(sstr, "%d %s", &rPid, Host);
+   if (gDebug > 2)
+      ErrorInfo("RpdCleanup: contacted by remote Host: %s, Pid: %d", Host,
+                rPid);
+
+   // Cleanup Auth tab
+   int ns;
+   if ((ns = RpdCleanupAuthTab(Host, rPid)))
+      ErrorInfo("RpdCleanup: %d not properly cleaned", ns);
+
+   // Trim Auth Tab file if call via RootdTerm (typically when rootd is shutting down ... )
+   if (!strcmp(Host, "all") || (rPid == 0))
+      RpdUpdateAuthTab(0, 0, 0);
+}
+
+//______________________________________________________________________________
+void RpdCheckSession(int period)
+{
+   // Period in seconds.
+
+   int speriod = 3600 * period;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckSession: enter: period: %d", period);
+
+   // Session file ...
+   char SessionFile[kMAXPATHLEN] = { 0 };
+   //   sprintf(SessionFile, "%s/rootd.%d", gTmpDir, getppid());
+   sprintf(SessionFile, "%s/rpd.run", gTmpDir);
+
+   // Reset
+   int i;
+   gNumAllow = gNumLeft = 0;
+   for (i = 0; i < kMAXSEC; i++) {
+      gAllowMeth[i] = -1;
+      gHaveMeth[i] = 1;
+   }
+
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckSession: sessionfile: %s", SessionFile);
+
+   // If it already exists, update auth tab or do nothing ...
+   struct stat st;
+   if (stat(SessionFile, &st) == 0) {
+      if (gDebug > 2)
+         ErrorInfo("RpdCheckSession: stat ok: mtime: %d", st.st_mtime);
+      if ((time(0) - st.st_mtime) > speriod)
+         RpdUpdateAuthTab(0, 0, 0);
+
+      FILE *fp = fopen(SessionFile, "r");
+
+      int ctim, nw;
+      char line[1024];
+      int meth[5];
+      while (fgets(line, sizeof(line), fp)) {
+         nw = sscanf(line, "%d %d %d %d %d %d", &ctim, &meth[4], &meth[0],
+                     &meth[1], &meth[2], &meth[3]);
+         if (nw > 1) {
+            gNumAllow = meth[4];
+            if (gNumAllow != (nw - 2)) {
+               ErrorInfo
+                   ("RpdCheckSession: inconsistency found in session file ( gNumAllow:%d nw:%d) - rescan",
+                    gNumAllow, nw);
+               goto rescan;
+            } else {
+               for (i = 0; i < gNumAllow; i++) {
+                  if (meth[i] >= 0 && meth[i] <= kMAXSEC) {
+                     gAllowMeth[i] = meth[i];
+                     gHaveMeth[meth[i]] = 1;
+                  } else {
+                     ErrorInfo
+                         ("RpdCheckSession: inconsistency found in session file (meth[%d]: %d) - rescan",
+                          i, meth[i]);
+                     goto rescan;
+                  }
+               }
+               gNumLeft = gNumAllow;
+            }
+         }
+      }
+      fclose(fp);
+      return;
+    rescan:
+      fclose(fp);
+
+   } else {
+      if (errno != ENOENT)
+         ErrorInfo
+             ("RpdCheckSession: file exists but problems from stat: errno:%d - recreating the file",
+              errno);
+   }
+
+   // Remove old files first ...
+   char cmd[kMAXPATHLEN] = { 0 };
+   sprintf(cmd, "ls -1 %s/rootd.* 2>/dev/null", gTmpDir);
+   FILE *fp = popen(cmd, "r");
+   i = 0;
+   if (fp != 0) {
+      int ch;
+      for (ch = fgetc(fp); ch != EOF; ch = fgetc(fp)) {
+         if (ch != 10) {
+            cmd[i++] = ch;
+         } else {
+            cmd[i] = '\0';
+            unlink(cmd);
+            i = 0;
+         }
+      }
+      if (i > 0) {
+         cmd[i] = '\0';
+         unlink(cmd);
+      }
+      pclose(fp);
+   }
+   // List of default authentication methods (to be save in the session file)
+   RpdDefaultAuthAllow();
+
+   char cmeth[200];
+   cmeth[0] = '\0';
+   sprintf(cmeth, "%d", gNumAllow);
+   for (i = 0; i < gNumAllow; i++) {
+      sprintf(cmeth, "%s %d", cmeth, gAllowMeth[i]);
+   }
+
+   // Create new file ...
+   fp = fopen(SessionFile, "w");
+   fprintf(fp, "%d %s\n", (int) time(0), cmeth);
+   fclose(fp);
+
+   // CleauUp Authentication Table
+   RpdUpdateAuthTab(-1, 0, 0);
+}
+
+//______________________________________________________________________________
+void RpdDefaultAuthAllow()
+{
+   // Check configuration options and running daemons to build a default list
+   // of secure methods.
+
+   if (gDebug > 2)
+      ErrorInfo("RpdDefaultAuthAllow: Enter");
+
+   // UsrPwdClear
+   gAllowMeth[gNumAllow] = 0;
+   gNumAllow++;
+   gNumLeft++;
+
+   // SSH
+   if (RpdCheckDaemon("sshd") > 0) {
+      if (RpdCheckSshd() > 0) {
+         gAllowMeth[gNumAllow] = 4;
+         gNumAllow++;
+         gNumLeft++;
+      }
+   } else if (RpdCheckSshd() > 0) {
+      if (gDebug > 0)
+         ErrorInfo
+             ("RpdDefaultAuthAllow: sshd not found by 'ps' but a process is listening on the specified port (%d)",
+              gSshdPort);
+      // Try at least connection to port ...
+      gAllowMeth[gNumAllow] = 4;
+      gNumAllow++;
+      gNumLeft++;
+   }
+   if (gNumAllow == 0) {
+      // Don't have this method
+      gHaveMeth[4] = 0;
+   }
+   // SRP
+#ifdef R__SRP
+   gAllowMeth[gNumAllow] = 1;
+   gNumAllow++;
+   gNumLeft++;
+#else
+   // Don't have this method
+   gHaveMeth[1] = 0;
+#endif
+
+   // Kerberos
+#ifdef R__KRB5
+   if (getuid() == 0) {
+      gAllowMeth[gNumAllow] = 2;
+      gNumAllow++;
+      gNumLeft++;
+   } else
+      gHaveMeth[2] = 0;
+#else
+   // Don't have this method
+   gHaveMeth[2] = 0;
+#endif
+
+   // Globus
+#ifdef R__GLBS
+   gAllowMeth[gNumAllow] = 3;
+   gNumAllow++;
+   gNumLeft++;
+#else
+   // Don't have this method
+   gHaveMeth[3] = 0;
+#endif
+
+   if (gDebug > 2) {
+      int i;
+      char temp[200];
+      temp[0] = '\0';
+      if (gNumAllow == 0)
+         strcpy(temp, "none");
+      for (i = 0; i < gNumAllow; i++) {
+         sprintf(temp, "%s %d", temp, gAllowMeth[i]);
+      }
+      ErrorInfo
+          ("RpdDefaultAuthAllow: default list of secure methods available: %s",
+           temp);
+   }
+}
+
+//______________________________________________________________________________
+int RpdCheckDaemon(const char *daemon)
+{
+   // Check the running of process 'daemon'.
+   // Info got from 'ps ax'.
+
+   char cmd[1024] = { 0 };
+   int ch, i = 0, cnt = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckDaemon: Enter ... %s", daemon);
+
+   // Return if empty
+   if (daemon == 0 || strlen(daemon) == 0)
+      return cnt;
+
+   // Build command
+   sprintf(cmd, "ps ax | grep %s 2>/dev/null", daemon);
+
+   // Run it ...
+   FILE *fp = popen(cmd, "r");
+   if (fp != 0) {
+      for (ch = fgetc(fp); ch != EOF; ch = fgetc(fp)) {
+         if (ch != 10) {
+            cmd[i++] = ch;
+         } else {
+            cmd[i] = '\0';
+            if (strstr(cmd, "grep") == 0 && strstr(cmd, "rootd") == 0
+                && strstr(cmd, "proofd") == 0) {
+               cnt++;
+               if (gDebug > 2)
+                  ErrorInfo("RpdCheckDaemon: read: %s", cmd);
+            }
+            i = 0;
+         }
+      }
+      if (i > 0) {
+         cmd[i] = '\0';
+         cnt++;
+         if (gDebug > 2)
+            ErrorInfo("RpdCheckDaemon: read: %s", cmd);
+      }
+      pclose(fp);
+      if (gDebug > 2)
+         ErrorInfo("RpdCheckDaemon: read %d lines", cnt);
+
+   } else {
+      ErrorInfo("RpdCheckDaemon: problems executing cmd ...");
+   }
+   return cnt;
+}
+
+//______________________________________________________________________________
+int RpdCheckSshd()
+{
+   // Tries to connect to sshd daemon on its standard port (22)
+   // Used if RpdCheckDaemon returns a negative result
+
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckSshd: Enter ... ");
+
+   // Standard SSH port
+   //  int SshdPort = 22;
+
+   // First get local host address
+   struct hostent *h = gethostbyname("localhost");
+   if (h == 0) {
+      // Make further attempt with HOSTNAME
+      if (getenv("HOSTNAME") == 0) {
+         ErrorInfo("RpdCheckSshd: unable to resolve local host name");
+         return 0;
+      } else {
+         h = gethostbyname(getenv("HOSTNAME"));
+         if (h == 0) {
+            ErrorInfo
+                ("RpdCheckSshd: local host name is unknown to gethostbyname: '%s'",
+                 getenv("HOSTNAME"));
+            return 0;
+         }
+      }
+   }
+   // Fill relevant sockaddr_in structure
+   struct sockaddr_in servAddr;
+   servAddr.sin_family = h->h_addrtype;
+   memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0],
+          h->h_length);
+   servAddr.sin_port = htons(gSshdPort);
+
+   // create AF_INET socket
+   int sd = socket(AF_INET, SOCK_STREAM, 0);
+   if (sd < 0) {
+      ErrorInfo("RpdCheckSshd: cannot open new AF_INET socket (errno:%d) ",
+                errno);
+      return 0;
+   }
+
+   /* bind any port number */
+   struct sockaddr_in localAddr;
+   localAddr.sin_family = AF_INET;
+   localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+   localAddr.sin_port = htons(0);
+   int rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr));
+   if (rc < 0) {
+      ErrorInfo("RpdCheckSshd: cannot bind to local port %u", gSshdPort);
+      return 0;
+   }
+   // connect to server
+   rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr));
+   if (rc < 0) {
+      ErrorInfo("RpdCheckSshd: cannot connect to local port %u",
+                gSshdPort);
+      return 0;
+   }
+   // Sshd successfully contacted
+   if (gDebug > 2)
+      ErrorInfo("RpdCheckSshd: success!");
+   return 1;
+}
+
+//______________________________________________________________________________
+void RpdUser(const char *sstr)
+{
+   // Check user id. If user id is not equal to rootd's effective uid, user
+   // will not be allowed access, unless effective uid = 0 (i.e. root).
+   const int kMaxBuf = 256;
+   char recvbuf[kMaxBuf];
+   char rootdpass[kMAXPATHLEN];
+   char specpass[64];
+   EMessageTypes kind;
+   struct passwd *pw;
+#ifdef R__SHADOWPW
+   struct spwd *spw;
+#endif
+   if (gDebug > 2)
+      ErrorInfo("RpdUser: Enter ... %s", sstr);
+
+   gAuth = 0;
+
+   // Nothing can be done if empty message
+   if (!*sstr) {
+      NetSend(kErrBadUser, kROOTD_ERR);
+      ErrorInfo("RpdUser: received empty string");
+      return;
+   }
+   // Parse input message
+   char *user = new char[strlen(sstr) + 1];
+   if (gClientProtocol > 8) {
+      int ulen, ofs, opt;
+      // Decode subject string
+      sscanf(sstr, "%d %d %d %d %s", &gRemPid, &ofs, &opt, &ulen, user);
+      user[ulen] = '\0';
+      gReUseRequired = (opt & kAUTH_REUSE_MSK);
+      gCryptRequired = (opt & kAUTH_CRYPT_MSK);
+      gOffSet = ofs;
+   } else {
+      strcpy(user, sstr);
+   }
+   if (gDebug > 2)
+      ErrorInfo("RpdUser: gReUseRequired: %d gCryptRequired: %d",
+                gReUseRequired, gCryptRequired);
+
+   ERootdErrors err = kErrNoUser;
+   if (!strcmp(gService, "rootd")) {
+      // Default anonymous account ...
+      if (!strcmp(user, "anonymous")) {
+         user[0] = '\0';
+         strcpy(user, "rootd");
+      }
+   }
+
+   if ((pw = getpwnam(user)) == 0) {
+      NetSend(err, kROOTD_ERR);
+      ErrorInfo("RpdUser: user %s unknown", user);
+      return;
+   }
+   // Check if of type anonymous ...
+   if (!strcmp(pw->pw_shell, "/bin/false")) {
+      err = kErrNoAnon;
+      gAnon = 1;
+      gReUseRequired = 0;
+   }
+   // If server is not started as root and user is not same as the
+   // one who started rootd then authetication is not ok.
+   uid_t uid = getuid();
+   if (uid && uid != pw->pw_uid) {
+      NetSend(kErrBadUser, kROOTD_ERR);
+      ErrorInfo("RpdUser: user not same as effective user of rootd");
+      return;
+   }
+   // Check if authorized
+   // If not anonymous, try to get passwd
+   // (if our system uses shadow passwds and we are not superuser
+   // we cannot authenticate users ...)
+   char *passw = 0;
+   if (gAnon == 0) {
+#ifdef R__SHADOWPW
+      // System V Rel 4 style shadow passwords
+      if ((spw = getspnam(user)) == 0) {
+         if (gDebug > 0) {
+            ErrorInfo("RpdUser: Shadow passwd not accessible for user %s",user);
+            ErrorInfo("RpdUser: trying normal or special root passwd");
+         }
+         passw = pw->pw_passwd;
+      } else
+         passw = spw->sp_pwdp;
+#else
+      passw = pw->pw_passwd;
+#endif
+      if (strlen(passw) == 0 || !strcmp(passw, "x")) {
+         // Try if special password is given via .rootdpass
+         sprintf(rootdpass, "%s/%s", pw->pw_dir, kRootdPass);
+
+         int fid = open(rootdpass, O_RDONLY);
+         if (fid != -1) {
+            int n;
+            if ((n = read(fid, specpass, sizeof(specpass) - 1)) > 0) {
+               passw = specpass;
+            }
+            close(fid);
+         }
+      }
+      // Check if successful
+      if (strlen(passw) == 0 || !strcmp(passw, "x")) {
+         NetSend(kErrNotAllowed, kROOTD_ERR);
+         ErrorInfo("RpdUser: passwd hash not available for user %s", user);
+         ErrorInfo
+             ("RpdUser: user %s cannot be authenticated with this method",
+              user);
+         return;
+      }
+   }
+   // Check if the administrator allows authentication
+   char cuid[20];
+   sprintf(cuid, "%d", pw->pw_uid);
+   if (gUserIgnLen[0] > 0 && strstr(gUserIgnore[0], cuid) != 0) {
+      NetSend(kErrNotAllowed, kROOTD_ERR);
+      ErrorInfo
+          ("RpdUser: user (%d,%s) not authorized to use UsrPwd method",
+           uid, pw->pw_name);
+      return;
+   }
+   if (gUserAlwLen[0] > 0 && strstr(gUserAllow[0], cuid) == 0) {
+      NetSend(kErrNotAllowed, kROOTD_ERR);
+      ErrorInfo
+          ("RpdUser: user (%d,%s) not authorized to use UsrPwd method",
+           uid, pw->pw_name);
+      return;
+   }
+   // Ok: Save username and go to next steps
+   strcpy(gUser, user);
+   SafeDelete(user);
+
+   if (gClientProtocol > 8) {
+
+      // Prepare status flag to send back
+      if (gAnon == 1) {
+         // Anonymous user: we will receive a text pass in the form user@remote.host.dom
+         NetSend(-1, kROOTD_AUTH);
+
+      } else {
+
+         if (gCryptRequired) {
+            // Named user: first we receive a session public key
+            // Ask for the RSA key
+            NetSend(1, kROOTD_RSAKEY);
+
+            NetRecv(gPubKey, kMAXPATHLEN, kind);
+            if (gDebug > 2)
+               ErrorInfo("RpdUser: got RSA key: (%d) '%s' len: %d", kind,
+                         gPubKey, strlen(gPubKey));
+
+            // Import key and determine its type
+            gRSAKey = RpdGetRSAKeys(gPubKey, 0);
+            if (gRSAKey == 0) {
+               ErrorInfo
+                   ("RpdUser: could not import a valid key - switch off reuse for this session");
+               gReUseRequired = 0;
+            }
+            // Determine Salt
+            char Salt[20] = { 0 };
+            int Slen = 0;
+
+            if (gReUseRequired) {
+               if (!strncmp(passw, "$1$", 3)) {
+                  // Shadow passwd
+                  char *pd = strstr(passw + 4, "$");
+                  Slen = (int) (pd - passw);
+                  strncpy(Salt, passw, Slen);
+                  Salt[Slen] = 0;
+               } else {
+                  Slen = 2;
+                  strncpy(Salt, passw, Slen);
+                  Salt[Slen] = 0;
+               }
+               if (gDebug > 2)
+                  ErrorInfo("RpdUser: salt: '%s' ",Salt);
+
+               // Send it over encrypted
+               if (RpdSecureSend(Salt) == -1) {
+                  ErrorInfo
+                      ("RpdUser: problems secure-sending salt - may result in corrupted salt");
+               }
+            } else {
+               NetSend("-1", kMESS_STRING);
+            }
+         } else {
+            // We continue the aythentication process in clear
+            NetSend(0, kROOTD_AUTH);
+         }
+      }
+
+   } else {
+      // If we are talking to a old client protocol
+      NetSend(0, kROOTD_AUTH);
+   }
+
+   // Get the password hash or anonymous string
+   if (NetRecv(recvbuf, kMaxBuf, kind) < 0) {
+      NetSend(kErrFatal, kROOTD_ERR);
+      ErrorInfo("RpdUser: error receiving message");
+      return;
+   }
+   if (kind != kROOTD_PASS) {
+      NetSend(kErrFatal, kROOTD_ERR);
+      ErrorInfo("RpdUser: received wrong message type: %d (expecting: %d)",
+                kind, (int) kROOTD_PASS);
+      return;
+   }
+   // Get passwd
+   char *passwd = 0;
+   if (gAnon == 0 && gClientProtocol > 8 && gCryptRequired) {
+
+      // Receive encrypted pass hash
+      if (RpdSecureRecv(&passwd) == -1) {
+         ErrorInfo
+             ("RpdUser: problems secure-receiving pass hash - may result in authentication failure ");
+      }
+
+   } else {
+
+      // Receive clear or anonymous pass
+      passwd = new char[strlen(recvbuf) + 1];
+
+      // Re-invert pass
+      int i, n = strlen(recvbuf);
+      for (i = 0; i < n; i++)
+         passwd[i] = ~recvbuf[i];
+      passwd[i] = '\0';
+
+      if (gDebug > 2 && gAnon)
+         ErrorInfo("RpdUser: received anonymous pass: '%s'", passwd);
+   }
+
+   // Check the passwd and login if ok ...
+   RpdPass(passwd);
+
+   SafeDelete(passwd);
+
+}
+
+//______________________________________________________________________________
+int RpdGuessClientProt(const char *buf, EMessageTypes kind)
+{
+   // Try a guess of the client protocol from what she/he sent over
+   // the net ...
+
+   if (gDebug > 2)
+      ErrorInfo("RpdGuessClientProt: Enter: buf: '%s', kind: %d", buf,
+                (int) kind);
+
+   // Assume same version as us.
+   int proto = 9;
+
+   // Clear authentication
+   if (kind == kROOTD_USER) {
+      char usr[64], rest[256];
+      int ns = sscanf(buf, "%s %s", usr, rest);
+      if (ns == 1)
+         proto = 8;
+   }
+   // SRP authentication
+   if (kind == kROOTD_SRPUSER) {
+      char usr[64], rest[256];
+      int ns = sscanf(buf, "%s %s", usr, rest);
+      if (ns == 1)
+         proto = 8;
+   }
+   // Kerberos authentication
+   if (kind == kROOTD_KRB5) {
+      if (strlen(buf) == 0)
+         proto = 8;
+   }
+
+   if (gDebug > 2)
+      ErrorInfo("RpdGuessClientProt: guess for gClientProtocol is %d",
+                proto);
+
+   // Return the guess
+   return proto;
+}
+
+//______________________________________________________________________________
+char *RpdGetRandString(int Opt, int Len)
+{
+   // Allocates and Fills a NULL terminated buffer of length Len+1 with
+   // Len random characters.
+   // Return pointer to the buffer (to be deleted by the caller)
+   // Opt = 0      any non dangerous char
+   //       1      letters and numbers  (upper and lower case)
+   //       2      hex characters       (upper and lower case)
+   //       3      crypt like           [a-zA-Z0-9./]
+
+   int iimx[4][4] = { { 0x0, 0xffffff08, 0xafffffff, 0x2ffffffe }, // Opt = 0
+                      { 0x0, 0x3ff0000,  0x7fffffe,  0x7fffffe },  // Opt = 1
+                      { 0x0, 0x3ff0000,  0x7e,       0x7e },       // Opt = 2
+                      { 0x0, 0x3ffc000,  0x7fffffe,  0x7fffffe }   // Opt = 3
+   };
+
+   char *cOpt[4] = { "Any", "LetNum", "Hex", "Crypt" };
+
+   //  Default option 0
+   if (Opt < 0 || Opt > 3) {
+      Opt = 0;
+      if (gDebug > 2)
+         ErrorInfo("RpdGetRandString: Unknown option: %d : assume 0", Opt);
+   }
+   if (gDebug > 2)
+      ErrorInfo("RpdGetRandString: Enter ... Len: %d %s", Len, cOpt[Opt]);
+
+   // Allocate buffer
+   char *Buf = new char[Len + 1];
+
+   // Get current time as seed for rand().
+   time_t curtime;
+   time(&curtime);
+   int seed = (int) curtime;
+
+   // feed seed
+   if (seed)
+      srand(seed);
+
+   // randomize
+   int k = 0;
+   int i, j, l, m, frnd;
+   while (k < Len) {
+      frnd = rand();
+      for (m = 7; m < 32; m += 7) {
+         i = 0x7F & (frnd >> m);
+         j = i / 32;
+         l = i - j * 32;
+         if ((iimx[Opt][j] & (1 << l))) {
+            Buf[k] = i;
+            k++;
+         }
+         if (k == Len)
+            break;
+      }
+   }
+
+   // NULL terminated
+   Buf[Len] = 0;
+   if (gDebug > 2)
+      ErrorInfo("RpdGetRandString: got '%s' ", Buf);
+
+   return Buf;
+}
+
+//______________________________________________________________________________
+int RpdGetRSAKeys(char *PubKey, int Opt)
+{
+   // Get public key from file PubKey (Opt == 1) or string PubKey (Opt == 0).
+
+   char Str[kMAXPATHLEN] = { 0 };
+   int KeyType = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdGetRSAKeys: enter: file opt '%s' %d ", PubKey, Opt);
+
+   if (!PubKey)
+      return KeyType;
+
+   FILE *fKey = 0;
+   // Parse input type
+   KeyType = 1;
+   if (Opt == 1) {
+      // Input is a File name: should get the string first
+      if (access(PubKey, R_OK)) {
+         ErrorInfo("RpdGetRSAKeys: Key File cannot be read - return ");
+         return 0;
+      }
+      fKey = fopen(PubKey, "r");
+      if (!fKey) {
+         ErrorInfo("RpdGetRSAKeys: cannot open key file %s ", PubKey);
+         return 0;
+      }
+      fgets(Str, sizeof(Str), fKey);
+   }
+
+   if (Opt == 0) {
+      strcpy(Str, PubKey);
+   }
+   if (strlen(Str) > 0) {
+      // The format is #<hex_n>#<hex_d>#
+      char *pd1 = strstr(Str, "#");
+      char *pd2 = strstr(pd1 + 1, "#");
+      char *pd3 = strstr(pd2 + 1, "#");
+      if (pd1 && pd2 && pd3) {
+         // Get <hex_n> ...
+         int l1 = (int) (pd2 - pd1 - 1);
+         char *RSA_n_exp = new char[l1 + 1];
+         strncpy(RSA_n_exp, pd1 + 1, l1);
+         RSA_n_exp[l1] = 0;
+         if (gDebug > 2)
+            ErrorInfo("RpdGetRSAKeys: got RSA_n_exp '%s' ", RSA_n_exp);
+         // Now <hex_d>
+         int l2 = (int) (pd3 - pd2 - 1);
+         char *RSA_d_exp = new char[l2 + 1];
+         strncpy(RSA_d_exp, pd2 + 1, l2);
+         RSA_d_exp[l2] = 0;
+         if (gDebug > 2)
+            ErrorInfo("RpdGetRSAKeys: got RSA_d_exp '%s' ", RSA_d_exp);
+
+         rsa_num_sget(&gRSA_n, RSA_n_exp);
+         rsa_num_sget(&gRSA_d, RSA_d_exp);
+
+         if (RSA_n_exp)
+            SafeDelete(RSA_n_exp);
+         if (RSA_d_exp)
+            SafeDelete(RSA_d_exp);
+
+      } else
+         return 0;
+   }
+
+   if (fKey)
+      fclose(fKey);
+
+   return KeyType;
+
+}
+
+//______________________________________________________________________________
+void RpdSavePubKey(char *PubKey, int OffSet)
+{
+   // Save RSA public key into file for later use by other rootd/proofd.
+
+   if (gRSAKey == 0)
+      return;
+
+   char PubKeyFile[kMAXPATHLEN];
+   sprintf(PubKeyFile, "%s/rpk_%d", gTmpDir, OffSet);
+   FILE *fKey = fopen(PubKeyFile, "w");
+   if (fKey) {
+      if (gRSAKey == 1) {
+         fprintf(fKey, "%s", PubKey);
+      }
+   } else {
+      ErrorInfo
+          ("RpdSavePubKey: cannot save public key: set entry inactive");
+      RpdCleanupAuthTab(gOpenHost, gRemPid);
+   }
+
+   if (fKey) {
+      fclose(fKey);
+      chmod(PubKeyFile, 0666);
+   }
+}
+
+//______________________________________________________________________________
+int RpdSecureSend(char *Str)
+{
+   // Encode null terminated Str using the session private key indcated by Key
+   // and sends it over the network.
+   // Returns number of bytes sent.or -1 in case of error.
+
+   char BufTmp[kMAXSECBUF];
+   char BufLen[20];
+
+   int sLen = strlen(Str) + 1;
+
+   int Ttmp = 0;
+   int Nsen = -1;
+
+   if (gRSAKey == 1) {
+      strncpy(BufTmp, Str, sLen);
+      BufTmp[sLen] = 0;
+      Ttmp = rsa_encode(BufTmp, sLen, gRSA_n, gRSA_d);
+      sprintf(BufLen, "%d", Ttmp);
+      NetSend(BufLen, kROOTD_ENCRYPT);
+      Nsen = NetSendRaw(BufTmp, Ttmp);
+      if (gDebug > 4)
+         ErrorInfo
+             ("RpdSecureSend: Local: sent %d bytes (expected: %d) (buffer '%s')",
+              Nsen, Ttmp, BufTmp);
+   } else {
+      ErrorInfo("RpdSecureSend: Unknown key option (%d) - return",
+                gRSAKey);
+   }
+
+   return Nsen;
+
+}
+
+//______________________________________________________________________________
+int RpdSecureRecv(char **Str)
+{
+   // Receive buffer and decode it in Str using key indicated by Key type.
+   // Return number of received bytes or -1 in case of error.
+
+   char BufTmp[kMAXSECBUF];
+   char BufLen[20];
+
+   int Nrec = -1;
+   // We must get a pointer ...
+   if (!Str)
+      return Nrec;
+
+   if (gDebug > 2)
+      ErrorInfo("RpdSecureRecv: enter ... (key is %d)", gRSAKey);
+
+   EMessageTypes kind;
+   NetRecv(BufLen, 20, kind);
+   int Len = atoi(BufLen);
+   if (gDebug > 4)
+      ErrorInfo("RpdSecureRecv: got len '%s' %d ", BufLen, Len);
+   if (!strncmp(BufLen, "-1", 2))
+      return Nrec;
+
+   // Now proceed
+   if (gRSAKey == 1) {
+      Nrec = NetRecvRaw(BufTmp, Len);
+      rsa_decode(BufTmp, Len, gRSA_n, gRSA_d);
+      if (gDebug > 2)
+         ErrorInfo("RpdSecureRecv: Local: decoded string: '%s' ", BufTmp);
+   } else {
+      ErrorInfo("RpdSecureRecv: Unknown key option (%d) - return",
+                gRSAKey);
+   }
+
+   *Str = new char[strlen(BufTmp) + 1];
+   strcpy(*Str, BufTmp);
+
+   return Nrec;
+
+}
+
+} // namespace ROOT
diff --git a/rpdutils/src/ssh.cxx b/rpdutils/src/ssh.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8f0a82888168085fa35032fe713eec14a6cdae2c
--- /dev/null
+++ b/rpdutils/src/ssh.cxx
@@ -0,0 +1,248 @@
+// @(#)root/rpdutils:$Name:  $:$Id: daemon.cxx,v 1.5 2002/10/28 14:22:51 rdm Exp $
+// Author: Gerardo Ganis    7/4/2003
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// Set of utilities for rootd/proofd daemon SSH authentication.         //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#if defined(linux)
+#   include <features.h>
+#   if __GNU_LIBRARY__ == 6
+#      ifndef R__GLIBC
+#         define R__GLIBC
+#      endif
+#   endif
+#endif
+#if defined(__MACH__) && !defined(__APPLE__)
+#   define R__GLIBC
+#endif
+
+#if defined(_AIX) || (defined(__FreeBSD__) && !defined(__alpha__))
+#   define USE_SIZE_T
+#elif defined(R__GLIBC) || (defined(__FreeBSD__) && defined(__alpha__))
+#   define USE_SOCKLEN_T
+#endif
+
+#include "rpdp.h"
+
+namespace ROOT {
+
+//--- Globals ------------------------------------------------------------------
+extern int gDebug;
+
+
+//______________________________________________________________________________
+int SshToolAllocateSocket(unsigned int Uid, unsigned int Gid, char **pipe)
+{
+   // Allocates internal UNIX socket for SSH-like authentication.
+   // Sets socket ownership to user for later use.
+   // On success returns ID of allocated socket and related pipe, -1 otherwise.
+
+   if (gDebug > 2)
+      ErrorInfo("SshToolAllocateSocket: enter: Uid:%d Gid:%d", Uid, Gid);
+
+   // Open socket
+   int sd;
+   if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+      ErrorInfo("SshToolAllocateSocket: error opening socket");
+      return -1;
+   }
+   // Prepare binding ...
+   struct sockaddr_un servAddr;
+   servAddr.sun_family = AF_UNIX;
+
+   // Determine unique pipe path: try with /tmp/rootdSSH_<random_string>
+   char fsun[] = "/tmp/rootdSSH_XXXXXXXX";
+   mktemp(fsun);
+   if (gDebug > 2)
+      ErrorInfo("SshToolAllocateSocket: unique pipe name is %s", fsun);
+
+   // Save path ...
+   strcpy(servAddr.sun_path, fsun);
+
+   // bind to socket
+   if (bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) {
+      ErrorInfo("SshToolAllocateSocket: unable to bind to socket %d", sd);
+      return -1;
+   }
+   // Activate listening
+   if (listen(sd, 5)) {
+      ErrorInfo
+          ("SshToolAllocateSocket: can't activate listening (errno: %d)",
+           errno);
+      return -1;
+   }
+
+   // Change ownerships and try to change them if needed
+   // This operaton is possible only as root ... but not always is needed
+   // so, do not stop in case of failure.
+   struct stat sst;
+
+   // The socket ...
+   fstat(sd, &sst);
+   if (sst.st_uid != Uid || sst.st_gid != Gid) {
+      if (fchown(sd, Uid, Gid)) {
+         if (gDebug > 0) {
+            ErrorInfo
+                ("SshToolAllocateSocket: fchown: could not change socket %d ownership (errno= %d) ",
+                 sd, errno);
+            ErrorInfo("SshToolAllocateSocket: socket (uid,gid) are: %d %d",
+                      sst.st_uid, sst.st_gid);
+            ErrorInfo
+                ("SshToolAllocateSocket: may follow authentication problems");
+         }
+      }
+   }
+   // The path ...
+   stat(fsun, &sst);
+   if (sst.st_uid != Uid || sst.st_gid != Gid) {
+      if (chown(fsun, Uid, Gid)) {
+         if (gDebug > 0) {
+            ErrorInfo
+                ("SshToolAllocateSocket: chown: could not change path '%s' ownership (errno= %d)",
+                 fsun, errno);
+            ErrorInfo("SshToolAllocateSocket: path (uid,gid) are: %d %d",
+                      sst.st_uid, sst.st_gid);
+            ErrorInfo
+                ("SshToolAllocateSocket: may follow authentication problems");
+         }
+      }
+   }
+   // Fill output
+   *pipe = strdup(fsun);
+
+   // return socket fd
+   return sd;
+}
+
+
+//______________________________________________________________________________
+void SshToolDiscardSocket(char *pipe, int sockfd)
+{
+   // Discards socket.
+
+   if (gDebug > 2)
+      ErrorInfo
+          ("SshToolDiscardSocket: discarding socket: pipe: %s, fd: %d",
+           pipe, sockfd);
+
+   // Unlink pipe
+   if (unlink(pipe) == -1) {
+      if (GetErrno() != ENOENT) {
+         ErrorInfo("SshToolDiscardSocket: unable to unlink %s"
+                   "(errno: %d, ENOENT= %d)", pipe, GetErrno(), ENOENT);
+      }
+   }
+   // close socket
+   close(sockfd);
+}
+
+//______________________________________________________________________________
+int SshToolNotifyFailure(char *Pipe)
+{
+   // Notifies failure of SSH authentication to relevant rootd/proofd process.
+
+   if (gDebug > 2)
+      ErrorInfo("SshToolNotifyFailure: notifying failure to pipe %s\n",
+                Pipe);
+
+   // Preparing socket connection
+   int sd;
+   struct sockaddr_un servAddr;
+   servAddr.sun_family = AF_UNIX;
+   strcpy(servAddr.sun_path, Pipe);
+   if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+      ErrorInfo("SshToolNotifyFailure: cannot open socket: exiting ");
+      return 1;
+   }
+   // Connecting to socket
+   int rc;
+   if ((rc =
+        connect(sd, (struct sockaddr *) &servAddr,
+                sizeof(servAddr))) < 0) {
+      ErrorInfo("SshToolNotifyFailure: cannot connect socket: exiting ");
+      return 1;
+   }
+   // Sending "KO" ...
+   char *okbuf = "KO";
+   rc = send(sd, okbuf, strlen(okbuf), 0);
+   if (rc != 2) {
+      ErrorInfo
+          ("SshToolNotifyFailure: sending might have been unsuccessful (bytes send: %d)",
+           rc);
+   }
+
+   return 0;
+}
+
+//______________________________________________________________________________
+int SshToolGetAuth(int UnixFd)
+{
+   int Auth = 0;
+
+   if (gDebug > 2)
+      ErrorInfo("SshToolGetAuth: accepting connections on socket %d",
+                UnixFd);
+
+   // Wait for verdict form sshd (via ssh2rpd ...)
+   struct sockaddr SunAddr;
+#if defined(USE_SIZE_T)
+   size_t SunAddrLen = sizeof(SunAddr);
+#elif defined(USE_SOCKLEN_T)
+   socklen_t SunAddrLen = sizeof(SunAddr);
+#else
+   int SunAddrLen = sizeof(SunAddr);
+#endif
+   int NewUnixFd =
+       accept(UnixFd, (struct sockaddr *) &SunAddr, &SunAddrLen);
+
+   char SshAuth[2] = { 0 };
+   int nr = NetRecvRaw(NewUnixFd, SshAuth, 2);
+   if (nr != 2) {
+      ErrorInfo
+          ("RootdSshAuth: incorrect reception from ssh2rpd: bytes:%d, buffer:%s ",
+           nr, SshAuth);
+   }
+   // Check authentication and notify to client
+   if (strncmp(SshAuth, "OK", 2) != 0) {
+      ErrorInfo("RootdSshAuth: user did not authenticate to sshd: %s (%d)",
+                SshAuth, strncmp(SshAuth, "OK", 2));
+   } else {
+      Auth = 1;
+   }
+
+   // Close local socket
+   close(NewUnixFd);
+
+   return Auth;
+}
+
+} // namespace ROOT