bug-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

a gserver patch


From: Mei-Hui Su
Subject: a gserver patch
Date: Tue, 1 May 2001 09:20:48 -0700 (PDT)

Hi,

  As part of the Globus Project (www.globus.org), we 
have developed a PKI based GSSAPI implementation called
the Grid Security infrastructure (GSI).  As part of this 
project, we are actively working within the IETF to 
standardize this binding.  We have been able to use this
GSS-API implementation with cyrus-sasl on both openldap 
and iplanet servers to do user authentication.

  We are interested in using GSI with cvs. With cvs's 
gserver, the GSI should just plugin and work. But we 
found that the implementation of the server's use of 
the GSS-API is not completely complient with the 
specification.  Specifically, we found, both client.c 
and server.c were not handling multiple server-client 
handshaking properly. For example, client did not check
if it is expected to receive a token from server (a check
on stat_maj for GSS_S_CONTINUE_NEEDED) before attempting
to do recv_byte. Server did not have a do-loop to match
client's and hence can not handle more than one hand-shake.
In Kerberos, there is just one round-trip and so these 
kind of problems did not show up.

  We were able to make some minimal changes to cvs's 
server and client code to use GSI instead of Kerberos.
These changes are backward compatible with the Kerberos 
GSS-API use and make the cvs cleint/server code's use of 
GSS-API more consistant with correct API usage.

  There are just 4 files that were changed. configure.in,
configure, src/server.c and src/client.c. The only GSI
specific code is in src/server.c which uses GSI's gridmap
to do access control, by mapping names in X.509 certificates
to local user ids.

  We would like you to consider incorporating these changes
into the CVS release.  Ideally, one would like to consider
using SASL as the security API used by CVS, rather then GSS-API.
We have significant experience with SASL as well, and if it
would make it more likely to include our mods, would consider
providing the necessary verions of the client and server.  


mei
(mei@isi.edu)

diff -u -r cvs/configure cvs-1.11/configure
--- cvs/configure       Thu Apr 26 13:54:31 2001
+++ cvs-1.11/configure  Tue Aug  1 09:13:25 2000
@@ -3232,7 +3232,8 @@
 
 CPPFLAGS=$hold_cppflags
 
-if (test "$ac_cv_header_gssapi_h" = "yes" ||
+if test "$ac_cv_header_krb5_h" = "yes" && 
+   (test "$ac_cv_header_gssapi_h" = "yes" ||
     test "$ac_cv_header_gssapi_gssapi_h" = "yes"); then
   cat >> confdefs.h <<\EOF
 #define HAVE_GSSAPI 1
@@ -3241,11 +3242,7 @@
   includeopt="${includeopt} -I$GSSAPI/include"
   # FIXME: This is ugly, but these things don't seem to be standardized.
   if test "$ac_cv_header_gssapi_h" = "yes"; then
-    if (test "$ac_cv_header_krb5_h" = "yes" &&
-        test "$GSSAPI_LIBS+set" = "set"); then
-      GSSAPI_LIB="-lgssapi -lkrb5 -lasn1 -ldes -lroken"
-    fi
-    LIBS="$LIBS -L$GSSAPI/lib $GSSAPI_LIBS"
+    LIBS="$LIBS -L$GSSAPI/lib -lgssapi -lkrb5 -lasn1 -ldes -lroken"
   else
     LIBS="$LIBS -L$GSSAPI/lib -lgssapi_krb5 -lkrb5 -lcrypto -lcom_err"
   fi
@@ -3253,7 +3250,7 @@
   CPPFLAGS="-I$GSSAPI/include $CPPFLAGS"
   if test "$ac_cv_header_gssapi_h" = "yes"; then
     cat > conftest.$ac_ext <<EOF
-#line 3257 "configure"
+#line 3254 "configure"
 #include "confdefs.h"
 #include <gssapi.h>
 EOF
@@ -3269,7 +3266,7 @@
 
   else
     cat > conftest.$ac_ext <<EOF
-#line 3273 "configure"
+#line 3270 "configure"
 #include "confdefs.h"
 #include <gssapi/gssapi.h>
 EOF
@@ -3288,7 +3285,7 @@
   # This is necessary on Irix 5.3, in order to link against libkrb5 --
   # there, an_to_ln.o refers to things defined only in -lgen.
   echo $ac_n "checking for compile in -lgen""... $ac_c" 1>&6
-echo "configure:3292: checking for compile in -lgen" >&5
+echo "configure:3289: checking for compile in -lgen" >&5
 ac_lib_var=`echo gen'_'compile | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3296,7 +3293,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lgen  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3300 "configure"
+#line 3297 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3307,7 +3304,7 @@
 compile()
 ; return 0; }
 EOF
-if { (eval echo configure:3311: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && 
test -s conftest${ac_exeext}; then
+if { (eval echo configure:3308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && 
test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3356,12 +3353,12 @@
 fi
 
 echo $ac_n "checking for gethostname""... $ac_c" 1>&6
-echo "configure:3360: checking for gethostname" >&5
+echo "configure:3357: checking for gethostname" >&5
 if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3365 "configure"
+#line 3362 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char gethostname(); below.  */
@@ -3384,7 +3381,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:3388: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && 
test -s conftest${ac_exeext}; then
+if { (eval echo configure:3385: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && 
test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_gethostname=yes"
 else
@@ -3449,14 +3446,14 @@
 if test "$enable_server" = yes; then
 
 echo $ac_n "checking for library containing crypt""... $ac_c" 1>&6
-echo "configure:3453: checking for library containing crypt" >&5
+echo "configure:3450: checking for library containing crypt" >&5
 if eval "test \"`echo '$''{'ac_cv_search_crypt'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_func_search_save_LIBS="$LIBS"
 ac_cv_search_crypt="no"
 cat > conftest.$ac_ext <<EOF
-#line 3460 "configure"
+#line 3457 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3467,7 +3464,7 @@
 crypt()
 ; return 0; }
 EOF
-if { (eval echo configure:3471: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && 
test -s conftest${ac_exeext}; then
+if { (eval echo configure:3468: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && 
test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_search_crypt="none required"
 else
@@ -3478,7 +3475,7 @@
 test "$ac_cv_search_crypt" = "no" && for i in crypt; do
 LIBS="-l$i  $ac_func_search_save_LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3482 "configure"
+#line 3479 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3489,7 +3486,7 @@
 crypt()
 ; return 0; }
 EOF
-if { (eval echo configure:3493: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && 
test -s conftest${ac_exeext}; then
+if { (eval echo configure:3490: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && 
test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_search_crypt="-l$i"
 break
@@ -3519,19 +3516,19 @@
 
 
 echo $ac_n "checking for cygwin32""... $ac_c" 1>&6
-echo "configure:3523: checking for cygwin32" >&5
+echo "configure:3520: checking for cygwin32" >&5
 if eval "test \"`echo '$''{'ccvs_cv_sys_cygwin32'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3528 "configure"
+#line 3525 "configure"
 #include "confdefs.h"
 
 int main() {
 return __CYGWIN32__;
 ; return 0; }
 EOF
-if { (eval echo configure:3535: \"$ac_compile\") 1>&5; (eval $ac_compile) 
2>&5; }; then
+if { (eval echo configure:3532: \"$ac_compile\") 1>&5; (eval $ac_compile) 
2>&5; }; then
   rm -rf conftest*
   ccvs_cv_sys_cygwin32=yes
 else
diff -u -r cvs/configure.in cvs-1.11/configure.in
--- cvs/configure.in    Thu Apr 26 13:54:31 2001
+++ cvs-1.11/configure.in       Tue Aug  1 09:13:25 2000
@@ -200,17 +200,14 @@
 AC_CHECK_HEADERS(krb5.h gssapi.h gssapi/gssapi.h gssapi/gssapi_generic.h)
 CPPFLAGS=$hold_cppflags
 
-if (test "$ac_cv_header_gssapi_h" = "yes" ||
+if test "$ac_cv_header_krb5_h" = "yes" && 
+   (test "$ac_cv_header_gssapi_h" = "yes" ||
     test "$ac_cv_header_gssapi_gssapi_h" = "yes"); then
   AC_DEFINE(HAVE_GSSAPI)
   includeopt="${includeopt} -I$GSSAPI/include"
   # FIXME: This is ugly, but these things don't seem to be standardized.
   if test "$ac_cv_header_gssapi_h" = "yes"; then
-    if (test "$ac_cv_header_krb5_h" = "yes" &&
-        test "$GSSAPI_LIBS+set" = "set"); then
-      GSSAPI_LIB="-lgssapi -lkrb5 -lasn1 -ldes -lroken"
-    fi
-    LIBS="$LIBS -L$GSSAPI/lib $GSSAPI_LIBS"
+    LIBS="$LIBS -L$GSSAPI/lib -lgssapi -lkrb5 -lasn1 -ldes -lroken"
   else
     LIBS="$LIBS -L$GSSAPI/lib -lgssapi_krb5 -lkrb5 -lcrypto -lcom_err"
   fi
diff -u -r cvs/src/client.c cvs-1.11/src/client.c
--- cvs/src/client.c    Fri Mar 23 11:08:18 2001
+++ cvs-1.11/src/client.c       Thu Jul  6 09:20:41 2000
@@ -4104,7 +4104,7 @@
      struct hostent *hostinfo;
 {
     char *str;
-    char buf[4000];
+    char buf[1024];
     gss_buffer_desc *tok_in_ptr, tok_in, tok_out;
     OM_uint32 stat_min, stat_maj;
     gss_name_t server_name;
@@ -4117,10 +4117,8 @@
     sprintf (buf, "cvs@%s", hostinfo->h_name);
     tok_in.length = strlen (buf);
     tok_in.value = buf;
-
-    if (gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
-                         &server_name) != GSS_S_COMPLETE)
-        error (1, 0, "could not import GSSAPI service name %s", buf);
+    gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
+                    &server_name);
 
     tok_in_ptr = GSS_C_NO_BUFFER;
     gcontext = GSS_C_NO_CONTEXT;
@@ -4134,7 +4132,6 @@
                                          | GSS_C_REPLAY_FLAG),
                                         0, NULL, tok_in_ptr, NULL, &tok_out,
                                         NULL, NULL);
-
        if (stat_maj != GSS_S_COMPLETE && stat_maj != GSS_S_CONTINUE_NEEDED)
        {
            OM_uint32 message_context;
@@ -4149,8 +4146,6 @@
            message_context = 0;
            gss_display_status (&new_stat_min, stat_min, GSS_C_MECH_CODE,
                                GSS_C_NULL_OID, &message_context, &tok_out);
-           (void) gss_release_name(&stat_min, &server_name);
-
            error (1, 0, "GSSAPI authentication failed: %s",
                   (char *) tok_out.value);
        }
@@ -4166,58 +4161,44 @@
 
            cbuf[0] = (tok_out.length >> 8) & 0xff;
            cbuf[1] = tok_out.length & 0xff;
-           if((send (sock, cbuf, 2, 0) < 0)
-                || (send (sock, tok_out.value, tok_out.length, 0) < 0))
-            {
-               (void) gss_release_buffer(&stat_min, &tok_out);
-                (void) gss_release_name(&stat_min, &server_name);
+           if (send (sock, cbuf, 2, 0) < 0)
+               error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
+           if (send (sock, tok_out.value, tok_out.length, 0) < 0)
                error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
-            }
 
-           (void) gss_release_buffer(&stat_min, &tok_out);
+           recv_bytes (sock, cbuf, 2);
+           need = ((cbuf[0] & 0xff) << 8) | (cbuf[1] & 0xff);
 
-            /* only if we still expecting a token from the server */
-           if(stat_maj == GSS_S_CONTINUE_NEEDED ) {
-               recv_bytes (sock, cbuf, 2);
-               need = ((cbuf[0] & 0xff) << 8) | (cbuf[1] & 0xff);
-
-               if (need > sizeof buf)
-               {
-                  int got;
+           if (need > sizeof buf)
+           {
+               int got;
 
                /* This usually means that the server sent us an error
                   message.  Read it byte by byte and print it out.
                   FIXME: This is a terrible error handling strategy.
                   However, even if we fix the server, we will still
                   want to do this to work with older servers.  */
-                  buf[0] = cbuf[0];
-                  buf[1] = cbuf[1];
-                  got = recv (sock, buf + 2, sizeof buf - 2, 0);
-                  if (got < 0)
-                   {
-                      error (1, 0, "recv() from server %s: %s",
-                             CVSroot_hostname, SOCK_STRERROR (SOCK_ERRNO));
-                   }
-                  buf[got + 2] = '\0';
-                  if (buf[got + 1] == '\n')
-                      buf[got + 1] = '\0';
-
-                   (void) gss_release_name(&stat_min, &server_name);
-                  error (1, 0, "error from server %s: %s", CVSroot_hostname,
-                       buf);
-               }
-
-               recv_bytes (sock, buf, need);
-               tok_in.length = need;
+               buf[0] = cbuf[0];
+               buf[1] = cbuf[1];
+               got = recv (sock, buf + 2, sizeof buf - 2, 0);
+               if (got < 0)
+                   error (1, 0, "recv() from server %s: %s",
+                          CVSroot_hostname, SOCK_STRERROR (SOCK_ERRNO));
+               buf[got + 2] = '\0';
+               if (buf[got + 1] == '\n')
+                   buf[got + 1] = '\0';
+               error (1, 0, "error from server %s: %s", CVSroot_hostname,
+                      buf);
            }
 
-           tok_in.value = buf;
-           tok_in_ptr = &tok_in;
-        }
-
-    } while (stat_maj == GSS_S_CONTINUE_NEEDED);
+           recv_bytes (sock, buf, need);
+           tok_in.length = need;
+       }
 
-    (void) gss_release_name(&stat_min, &server_name);
+       tok_in.value = buf;
+       tok_in_ptr = &tok_in;
+    }
+    while (stat_maj == GSS_S_CONTINUE_NEEDED);
 
     return 1;
 }
diff -u -r cvs/src/server.c cvs-1.11/src/server.c
--- cvs/src/server.c    Fri Apr 20 10:23:49 2001
+++ cvs-1.11/src/server.c       Fri Jul 28 13:18:40 2000
@@ -40,6 +40,7 @@
 #endif
 
 #ifdef HAVE_GSSAPI
+
 #include <netdb.h>
 
 #ifdef HAVE_GSSAPI_H
@@ -56,17 +57,9 @@
 #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
 #endif
 
-#ifdef HAVE_KERBEROS
 /* We use Kerberos 5 routines to map the GSSAPI credential to a user
    name.  */
 #include <krb5.h>
-#endif
-
-#ifdef HAVE_GSI
-/* We use GSI's gridmap routines to map the GSSAPI credential to a user
-   name.  */
-#include <globus_gss_assist.h>
-#endif
 
 /* We need this to wrap data.  */
 static gss_ctx_id_t gcontext;
@@ -192,48 +185,6 @@
 static int fd_buffer_block PROTO((void *, int));
 static int fd_buffer_shutdown PROTO((void *));
 
-#ifdef HAVE_GSI
-char *
-variable_get (name)
-    char *name;
-{
-    char *p; /* to point to the val */
-    Node *node;
-
-    if (variable_list == NULL)
-        return NULL;
-
-    node = findnode (variable_list, name);
-    if (node != NULL)
-    {
-        return node->data;
-    }
-    return NULL;
-}
-
-void 
-retrieve_gsi_conf()
-{
-    char *conffile;
-
-    conffile=variable_get("GSI_CONF_FILE");
-
-    if(conffile) {
-       char buf[1024];
-       FILE *fp;
-       fp=fopen(conffile,"r");
-       if(fp) {
-         while (fgets(buf, sizeof buf, fp) != NULL) {
-           if(buf[strlen(buf)-1]=='\n') /* remove the newline */
-             buf[strlen(buf)-1]='\0'; /* remove the newline */
-           (void) putenv(xstrdup(buf));
-         }
-         fclose(fp);
-       } 
-    }
-}
-#endif
-
 /* Initialize a buffer built on a file descriptor.  FD is the file
    descriptor.  INPUT is nonzero if this is for input, zero if this is
    for output.  MEMORY is the function to call when a memory error
@@ -5701,10 +5652,6 @@
     {
 #ifdef HAVE_GSSAPI
        free (tmp);
-
-#ifdef HAVE_GSI
-retrieve_gsi_conf();
-#endif
        gserver_authenticate_connection ();
        return;
 #else
@@ -5902,8 +5849,8 @@
     char hostname[MAXHOSTNAMELEN];
     struct hostent *hp;
     gss_buffer_desc tok_in, tok_out;
-    char buf[4000];
-    OM_uint32 stat_min, stat_maj, ret;
+    char buf[1024];
+    OM_uint32 stat_min, ret;
     gss_name_t server_name, client_name;
     gss_cred_id_t server_creds;
     int nbytes;
@@ -5927,31 +5874,26 @@
     if (gss_acquire_cred (&stat_min, server_name, 0, GSS_C_NULL_OID_SET,
                          GSS_C_ACCEPT, &server_creds,
                          NULL, NULL) != GSS_S_COMPLETE)
-    { 
-        (void) gss_release_name(&stat_min, &server_name);
        error (1, 0, "could not acquire GSSAPI server credentials");
-    }
 
     gss_release_name (&stat_min, &server_name);
 
-    gcontext = GSS_C_NO_CONTEXT;
-
-    do {
     /* The client will send us a two byte length followed by that many
        bytes.  */
-       if (fread (buf, 1, 2, stdin) != 2)
-           error (1, errno, "read of length failed");
+    if (fread (buf, 1, 2, stdin) != 2)
+       error (1, errno, "read of length failed");
 
-       nbytes = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
-       assert (nbytes <= sizeof buf);
+    nbytes = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
+    assert (nbytes <= sizeof buf);
 
-       if (fread (buf, 1, nbytes, stdin) != nbytes)
-           error (1, errno, "read of data failed");
+    if (fread (buf, 1, nbytes, stdin) != nbytes)
+       error (1, errno, "read of data failed");
 
-       tok_in.length = nbytes;
-       tok_in.value = buf;
+    gcontext = GSS_C_NO_CONTEXT;
+    tok_in.length = nbytes;
+    tok_in.value = buf;
 
-       stat_maj = gss_accept_sec_context (&stat_min,
+    if (gss_accept_sec_context (&stat_min,
                                 &gcontext,     /* context_handle */
                                 server_creds,  /* verifier_cred_handle */
                                 &tok_in,       /* input_token */
@@ -5961,34 +5903,12 @@
                                 &tok_out,      /* output_token */
                                 &ret,
                                 NULL,          /* ignore time_rec */
-                                NULL);         /* ignore del_cred_handle */
-       if(stat_maj != GSS_S_COMPLETE && stat_maj != GSS_S_CONTINUE_NEEDED)
-       {
-           error (1, 0, "could not verify credentials");
-       }
-
-        if (tok_out.length != 0)
-        {
-           char cbuf[2];
-
-           cbuf[0] = (tok_out.length >> 8) & 0xff;
-           cbuf[1] = tok_out.length & 0xff;
-            if (fwrite (cbuf, 1, 2, stdout) != 2
-               || (fwrite (tok_out.value, 1, tok_out.length, stdout)
-                       != tok_out.length))
-            {
-               (void) gss_release_buffer(&stat_min, &tok_out);
-               error (1, errno, "fwrite failed");
-            }
-
-           (void) gss_release_buffer(&stat_min, &tok_out);
-        }
-
-        fflush(stdout);
-
-    } while (stat_maj == GSS_S_CONTINUE_NEEDED);
+                                NULL)          /* ignore del_cred_handle */
+       != GSS_S_COMPLETE)
+    {
+       error (1, 0, "could not verify credentials");
+    }
 
-#ifdef HAVE_KERBEROS
     /* FIXME: Use Kerberos v5 specific code to authenticate to a user.
        We could instead use an authentication to access mapping.  */
     {
@@ -5999,51 +5919,27 @@
        krb5_init_context (&kc);
        if (gss_display_name (&stat_min, client_name, &desc,
                              &mechid) != GSS_S_COMPLETE
-            || krb5_parse_name (kc, ((gss_buffer_t) &desc)->value, &p) != 0
-            || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0
-            || krb5_kuserok (kc, p, buf) != TRUE)
-        {
+           || krb5_parse_name (kc, ((gss_buffer_t) &desc)->value, &p) != 0
+           || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0
+           || krb5_kuserok (kc, p, buf) != TRUE)
+       {
            error (1, 0, "access denied");
        }
-        krb5_free_principal (kc, p);
-        krb5_free_context (kc);
+       krb5_free_principal (kc, p);
+       krb5_free_context (kc);
     }
-#endif
-#ifdef HAVE_GSI
-/* get the name from the last token */
-    {
-        gss_buffer_desc name_token ;
-        char *authcid=NULL;
-        char *ubuf=NULL;
 
-        if (gss_display_name (&stat_min, client_name, &name_token,
-                              NULL) != GSS_S_COMPLETE)
-        {
-            error (1, 0, "access denied");
-        }
-        if(name_token.value)
-        {
-           authcid=strdup((char *)name_token.value);
-            gss_release_buffer(&stat_min, &name_token);
-        } else {
-            error (1, 0, "access denied: name_token is NULL?");
-        }
-
-        if(authcid==NULL ||
-             globus_gss_assist_gridmap(authcid, &ubuf)==1)
-        {
-            error (1, 0, "access denied: gridmap lookup failed");
-        }
+    if (tok_out.length != 0)
+    {
+       char cbuf[2];
 
-        if(authcid) free(authcid);
-        if(ubuf)
-       {
-           strcpy(buf,ubuf);
-            free(ubuf);
-       }       
+       cbuf[0] = (tok_out.length >> 8) & 0xff;
+       cbuf[1] = tok_out.length & 0xff;
+       if (fwrite (cbuf, 1, 2, stdout) != 2
+           || (fwrite (tok_out.value, 1, tok_out.length, stdout)
+               != tok_out.length))
+           error (1, errno, "fwrite failed");
     }
-#endif
-    (void) gss_release_name(&stat_min, &client_name);
 
     switch_to_user (buf);
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]