]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Merge trunk changes from r23909 to r23929
authorGreg Hudson <ghudson@mit.edu>
Sat, 24 Apr 2010 15:02:18 +0000 (15:02 +0000)
committerGreg Hudson <ghudson@mit.edu>
Sat, 24 Apr 2010 15:02:18 +0000 (15:02 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/iakerb@23930 dc483132-0cff-0310-8789-dd5450dbe970

16 files changed:
src/Makefile.in
src/config/post.in
src/kdc/dispatch.c
src/lib/gssapi/krb5/init_sec_context.c
src/lib/gssapi/mechglue/g_accept_sec_context.c
src/lib/krb5/krb/get_creds.c
src/lib/krb5/krb/s4u_creds.c
src/lib/krb5/krb/str_conv.c
src/lib/krb5/os/changepw.c
src/slave/kproplog.c
src/tests/dejagnu/config/default.exp
src/tests/dejagnu/krb-standalone/standalone.exp
src/tests/dejagnu/t_inetd.c
src/tests/hammer/kdc5_hammer.c
src/util/k5test.py
src/util/support/plugins.c

index ed0e69c14214a6ed059298f52a32f6f49a967cc1..2f64c497bac42c1368650b7e27533757f3c633ba 100644 (file)
@@ -14,8 +14,10 @@ SUBDIRS=util include lib \
        plugins/preauth/encrypted_challenge \
        kdc kadmin slave clients appl tests \
        config-files gen-manpages
-BUILDTOP=$(REL)$(C)
+BUILDTOP=$(REL).
 LOCALINCLUDES = -I$(srcdir) 
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
 
 SRCS =  
 HDRS = 
@@ -625,8 +627,25 @@ check-unix:: krb5-config
 check-prerecurse: fake-install
 
 # Create a test realm and spawn a shell in an environment pointing to it.
-testrealm: fake-install
-       PYTHONPATH=$(top_srcdir)/util $(PYTHON) $(srcdir)/util/testrealm.py
+testrealm: fake-install runenv.py
+       PYTHONPATH=$(BUILDTOP):$(top_srcdir)/util $(PYTHON) $(srcdir)/util/testrealm.py
+
+# environment variable settings to propagate to Python-based tests
+
+check-pytests-yes: runenv.py
+
+pyrunenv.vals: Makefile
+       $(KRB5_RUN_ENV) \
+       for i in $(KRB5_RUN_VARS); do \
+               eval echo 'env['\\\'$$i\\\''] = '\\\'\$$$$i\\\'; \
+       done > $@
+
+runenv.py: pyrunenv.vals
+       echo 'env = {}' > $@
+       cat pyrunenv.vals >> $@
+
+clean-unix::
+       $(RM) runenv.py pyrunenv.vals
 
 COV_BUILD=     cov-build
 COV_ANALYZE=   cov-analyze
index c4cdcae3bf9577f8941b5fce07c911d1cc35d6fa..861117c9e9e7a22f138849766f64604d60f8eb3d 100644 (file)
@@ -136,10 +136,10 @@ check-unix:: check-pytests
 
 check-pytests:: check-pytests-@HAVE_PYTHON@
 
-check-pytests-yes: runenv.py
+check-pytests-yes:
        @pytests="$(PYTESTS)"; \
        for t in $$pytests; do \
-               echo PYTHONPATH=`pwd`:$(top_srcdir)/util VALGRIND="$(VALGRIND)" \
+               echo PYTHONPATH=$(BUILDTOP):$(top_srcdir)/util VALGRIND="$(VALGRIND)" \
                        $(PYTHON) $(srcdir)/$$t $(PYTESTFLAGS); \
                PYTHONPATH=`pwd`:$(top_srcdir)/util VALGRIND="$(VALGRIND)" \
                        $(PYTHON) $(srcdir)/$$t $(PYTESTFLAGS) || exit 1; \
@@ -150,22 +150,11 @@ check-pytests-no:
                echo "+++ Skipping because Python not available: $(PYTESTS)"; \
        fi
 
-pyrunenv.vals: Makefile
-       $(KRB5_RUN_ENV) \
-       for i in $(KRB5_RUN_VARS); do \
-               eval echo 'env['\\\'$$i\\\''] = '\\\'\$$$$i\\\'; \
-       done > $@
-
-runenv.py: pyrunenv.vals
-       echo 'env = {}' > $@
-       cat pyrunenv.vals >> $@
-
 clean:: clean-$(WHAT)
 
 clean-unix::
        $(RM) $(OBJS) $(DEPTARGETS_CLEAN) $(EXTRA_FILES) et-[ch]-*.et et-[ch]-*.[ch]
        -$(RM) -r $(top_srcdir)/autom4te.cache
-       $(RM) runenv.py pyrunenv.vals
 
 clean-windows::
        $(RM) *.$(OBJEXT)
index 207fa390ad17309de493736f19b246d90134a4c5..63ff3b38d82ab36ad7c36b2875a5eaf393e09cad 100644 (file)
@@ -111,7 +111,7 @@ dispatch(void *cb, struct sockaddr *local_saddr, const krb5_fulladdr *from,
         retval = KRB5KRB_AP_ERR_MSG_TYPE;
 #ifndef NOCACHE
     /* put the response into the lookaside buffer */
-    if (!retval && *response != NULL)
+    if (!retval)
         kdc_insert_lookaside(pkt, *response);
 #endif
 
index ea0dc9db91798db48f31116c997d66377768d22a..7d539e52423e0cb9144833a73464a0d3d574a80e 100644 (file)
@@ -128,10 +128,12 @@ static krb5_error_code get_credentials(context, cred, server, now,
     krb5_creds **out_creds;
 {
     krb5_error_code     code;
-    krb5_creds          in_creds, evidence_creds;
+    krb5_creds          in_creds, evidence_creds, *result_creds = NULL;
     krb5_flags          flags = 0;
     krb5_principal      cc_princ = NULL;
 
+    *out_creds = NULL;
+
     k5_mutex_assert_locked(&cred->lock);
     memset(&in_creds, 0, sizeof(krb5_creds));
     memset(&evidence_creds, 0, sizeof(krb5_creds));
@@ -200,7 +202,7 @@ static krb5_error_code get_credentials(context, cred, server, now,
         flags |= KRB5_GC_CACHED;
 
     code = krb5_get_credentials(context, flags, cred->ccache,
-                                &in_creds, out_creds);
+                                &in_creds, &result_creds);
     if (code == KRB5_CC_NOTFOUND && cred->password.data != NULL &&
         !cred->iakerb_mech) {
         krb5_creds tgt_creds;
@@ -232,7 +234,7 @@ static krb5_error_code get_credentials(context, cred, server, now,
 
     if (flags & KRB5_GC_CONSTRAINED_DELEGATION) {
         if (!krb5_principal_compare(context, cred->name->princ,
-                                    (*out_creds)->client)) {
+                                    result_creds->client)) {
             /* server did not support constrained delegation */
             code = KRB5_KDCREP_MODIFIED;
             goto cleanup;
@@ -244,16 +246,19 @@ static krb5_error_code get_credentials(context, cred, server, now,
      * boundaries) because accept_sec_context code is also similarly
      * non-forgiving.
      */
-    if (!krb5_gss_dbg_client_expcreds && *out_creds != NULL &&
-        (*out_creds)->times.endtime < now) {
+    if (!krb5_gss_dbg_client_expcreds && result_creds->times.endtime < now) {
         code = KRB5KRB_AP_ERR_TKT_EXPIRED;
         goto cleanup;
     }
 
+    *out_creds = result_creds;
+    result_creds = NULL;
+
 cleanup:
     krb5_free_authdata(context, in_creds.authdata);
     krb5_free_principal(context, cc_princ);
     krb5_free_cred_contents(context, &evidence_creds);
+    krb5_free_creds(context, result_creds);
 
     return code;
 }
@@ -535,7 +540,7 @@ kg_new_connection(
 {
     OM_uint32 major_status;
     krb5_error_code code;
-    krb5_creds *k_cred;
+    krb5_creds *k_cred = NULL;
     krb5_gss_ctx_id_rec *ctx, *ctx_free;
     krb5_timestamp now;
     gss_buffer_desc token;
@@ -671,8 +676,6 @@ kg_new_connection(
             goto fail;
     }
 
-    krb5_free_creds(context, k_cred);
-    k_cred = NULL;
     ctx->enc = NULL;
     ctx->seq = NULL;
     ctx->have_acceptor_subkey = 0;
@@ -725,6 +728,7 @@ kg_new_connection(
     }
 
 fail:
+    krb5_free_creds(context, k_cred);
     if (ctx_free) {
         if (ctx_free->auth_context)
             krb5_auth_con_free(context, ctx_free->auth_context);
index b4b152551c34eee7f68e1e631bc1951658571e05..498bfc4569dac3fc11165db1e313f91c2cdcc618 100644 (file)
@@ -356,9 +356,6 @@ error_out:
        free(union_ctx_id);
     }
 
-    if (output_token->length)
-       (void) gss_release_buffer(&temp_minor_status, output_token);
-
     if (src_name)
        *src_name = GSS_C_NO_NAME;
 
index 36624af1f0fb99d9ad917b5cef33ba72bf190947..6099c6d919af236264d55fedd61e01d51c85ee5a 100644 (file)
@@ -496,8 +496,10 @@ try_fallback_realm(krb5_context context, krb5_tkt_creds_context ctx)
         return code;
 
     /* Give up if the fallback realm isn't any different. */
-    if (data_eq_string(ctx->server->realm, hrealms[0]))
+    if (data_eq_string(ctx->server->realm, hrealms[0])) {
+        krb5_free_host_realm(context, hrealms);
         return ctx->reply_code;
+    }
 
     /* Rewrite server->realm to be the fallback realm. */
     krb5_free_data_contents(context, &ctx->server->realm);
index 02485e851e65734df58c7cf3120d0e2e83f9582b..da6dd0c99045fd114cd942d5b85816f58e61d6ea 100644 (file)
@@ -685,11 +685,17 @@ krb5_get_credentials_for_user(krb5_context context, krb5_flags options,
     if (code != 0)
         goto cleanup;
 
-    code = krb5_get_credentials(context, options | KRB5_GC_CACHED,
-                                ccache, in_creds, out_creds);
-    if ((code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE)
-        || options & KRB5_GC_CACHED)
-        goto cleanup;
+    if (in_creds->client != NULL &&
+        in_creds->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
+       /* Post-canonicalisation check for enterprise principals */
+       krb5_creds mcreds = *in_creds;
+       mcreds.client = realm;
+       code = krb5_get_credentials(context, options | KRB5_GC_CACHED,
+                                   ccache, &mcreds, out_creds);
+       if ((code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE)
+           || (options & KRB5_GC_CACHED))
+           goto cleanup;
+    }
 
     code = krb5_get_self_cred_from_kdc(context, options, ccache,
                                        in_creds, subject_cert,
index 1f2edcc66f0d911616a743cabe9be8396385c8b4..6ed639245ac0e4fe0efb193fdfb3648f09ab8c0e 100644 (file)
@@ -300,7 +300,6 @@ krb5_deltat_to_string(krb5_deltat deltat, char *buffer, size_t buflen)
      * This will break if bytes are more than 8 bits.
      */
 #define MAX_CHARS_FOR_INT_TYPE(TYPE)    ((int) (2 + 2.408241 * sizeof (TYPE)))
-    char tmpbuf[MAX_CHARS_FOR_INT_TYPE(int) * 4 + 8];
 
     days = (int) (deltat / (24*3600L));
     dt = deltat % (24*3600L);
@@ -309,7 +308,6 @@ krb5_deltat_to_string(krb5_deltat deltat, char *buffer, size_t buflen)
     minutes = (int) (dt / 60);
     seconds = (int) (dt % 60);
 
-    memset (tmpbuf, 0, sizeof (tmpbuf));
     if (days == 0)
         snprintf(buffer, buflen, "%d:%02d:%02d", hours, minutes, seconds);
     else if (hours || minutes || seconds)
@@ -319,14 +317,6 @@ krb5_deltat_to_string(krb5_deltat deltat, char *buffer, size_t buflen)
     else
         snprintf(buffer, buflen, "%d %s", days,
                  (days > 1) ? "days" : "day");
-    if (tmpbuf[sizeof(tmpbuf)-1] != 0)
-        /* Something must be very wrong with my math above, or the
-           assumptions going into it...  */
-        abort ();
-    if (strlen (tmpbuf) > buflen)
-        return ENOMEM;
-    else
-        strncpy (buffer, tmpbuf, buflen);
     return 0;
 }
 
index 7cab0d63d1f0b4be0381faa492c0f55d979fdf36..25840b6d58c6d61531fcd554637b7c8b7d592b38 100644 (file)
@@ -140,7 +140,8 @@ kpasswd_sendto_msg_callback(struct conn_state *conn,
         local_kaddr.length = sizeof(ss2sin(&local_addr)->sin_addr);
         local_kaddr.contents = (krb5_octet *) &ss2sin(&local_addr)->sin_addr;
     } else if (local_addr.ss_family == AF_INET6 &&
-               ss2sin6(&local_addr)->sin6_addr.s6_addr != 0) {
+               memcmp(ss2sin6(&local_addr)->sin6_addr.s6_addr,
+                      in6addr_any.s6_addr, sizeof(in6addr_any.s6_addr)) != 0) {
         local_kaddr.addrtype = ADDRTYPE_INET6;
         local_kaddr.length = sizeof(ss2sin6(&local_addr)->sin6_addr);
         local_kaddr.contents = (krb5_octet *) &ss2sin6(&local_addr)->sin6_addr;
index 0134631b0785d22129838f32254472a00214f3e5..0af30d92cba9f9aa9633287b6023982c0ab58fa9 100644 (file)
@@ -74,20 +74,40 @@ print_flags(unsigned int flags)
     }
 }
 
+/* ctime() for uint32_t* */
+static char *
+ctime_uint32(uint32_t *time32)
+{
+    time_t tmp;
+    tmp = *time32;
+    return ctime(&tmp);
+}
+
 /*
  * Display time information.
  */
 static void
-print_time(unsigned int *timep)
+print_time(uint32_t *timep)
 {
     if (*timep == 0L)
         printf("\t\t\tNone\n");
     else {
-        time_t ltime = *timep;
-        printf("\t\t\t%s", ctime(&ltime));
+        printf("\t\t\t%s", ctime_uint32(timep));
     }
 }
 
+static void
+print_deltat(uint32_t *deltat)
+{
+    krb5_error_code ret;
+    static char buf[30];
+    ret = krb5_deltat_to_string(*deltat, buf, sizeof(buf));
+    if (ret)
+        printf("\t\t\t(error)\n");
+    else
+        printf("\t\t\t%s\n", buf);
+}
+
 /*
  * Display string in hex primitive.
  */
@@ -251,13 +271,13 @@ print_attr(kdbe_val_t *val, int vverbose)
     case AT_MAX_LIFE:
         (void) printf(_("\t\tMaximum ticket life\n"));
         if (vverbose) {
-            print_time(&val->kdbe_val_t_u.av_max_life);
+            print_deltat(&val->kdbe_val_t_u.av_max_life);
         }
         break;
     case AT_MAX_RENEW_LIFE:
         (void) printf(_("\t\tMaximum renewable life\n"));
         if (vverbose) {
-            print_time(&val->kdbe_val_t_u.av_max_renew_life);
+            print_deltat(&val->kdbe_val_t_u.av_max_renew_life);
         }
         break;
     case AT_EXP:
@@ -447,7 +467,7 @@ print_update(kdb_hlog_t *ulog, uint32_t entry, unsigned int verbose)
             (void) printf(_("\tUpdate time stamp : None\n"));
         else
             (void) printf(_("\tUpdate time stamp : %s"),
-                          ctime((time_t *)&(indx_log->kdb_time.seconds)));
+                          ctime_uint32(&indx_log->kdb_time.seconds));
 
         (void) printf(_("\tAttributes changed : %d\n"),
                       upd.kdb_update.kdbe_t_len);
@@ -581,12 +601,11 @@ main(int argc, char **argv)
             (void) printf(_("\tFirst time stamp : None\n"));
         else {
             (void) printf(_("\tFirst time stamp : %s"),
-                          ctime((time_t *)
-                                &(ulog->kdb_first_time.seconds)));
+                          ctime_uint32(&ulog->kdb_first_time.seconds));
         }
 
         (void) printf(_("\tLast time stamp : %s\n"),
-                      ctime((time_t *)&(ulog->kdb_last_time.seconds)));
+                      ctime_uint32(&ulog->kdb_last_time.seconds));
     }
 
     if ((!headeronly) && ulog->kdb_num) {
index 382c17409eb09ad16aa79a135a8395cc1c6b96fe..1638a5a0d4a24d38d34a8cfcccd1c144fecb1d84 100644 (file)
@@ -2107,6 +2107,41 @@ proc kinit { name pass standalone } {
 
     return 1
 }
+
+proc kinit_renew { name pass standalone } {
+    global REALMNAME
+    global KINIT
+    global spawn_id
+
+    spawn $KINIT -5 -f $name@$REALMNAME
+    expect {
+       "Password for $name@$REALMNAME:" {
+           verbose "kinit started"
+       }
+       timeout {
+           fail "kinit"
+           return 0
+       }
+       eof {
+           fail "kinit"
+           return 0
+       }
+    }
+    send "$pass\r"
+    expect eof
+    if ![check_exit_status kinit] {
+       return 0
+    }
+
+    spawn $KINIT -R
+    expect eof
+    if ![check_exit_status "kinit_renew"] {
+       return 0
+    }
+
+    return 1
+}
+
 # Retrieve a ticket using FAST armor
 proc kinit_fast { name pass standalone } {
     global REALMNAME
index c511798b445d80f5a8cc1894cc2e78cfaa12c95a..dbaf95dbd75983ac6043d62cd4c9c557acb25517 100644 (file)
@@ -201,6 +201,10 @@ proc doit { } {
        return
     }
 
+    if ![kinit_renew krbtest/admin adminpass$KEY 1] {
+       return
+    }
+
     # Make sure that klist can see the ticket.
     if ![do_klist "krbtest/admin@$REALMNAME" "krbtgt/$REALMNAME@$REALMNAME" "klist"] {
        return
index dbee2838df746b4e9f323d8cd67c2fef90d5f22d..72d51fd7f6fdb4e3d60c11d220880d8370d9d47b 100644 (file)
@@ -46,6 +46,7 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <stdio.h>
+#include <string.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <signal.h>
@@ -97,6 +98,7 @@ main(argc, argv)
     (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one,
                       sizeof (one));
 
+    memset(&l_inaddr, 0, sizeof(l_inaddr));
     l_inaddr.sin_family = AF_INET;
     l_inaddr.sin_addr.s_addr = 0;
     l_inaddr.sin_port = port;
index 63ac31e2a4e410944a4ce5c0d87f1797ceba2549..97e03826903e44f05cbfb07bc2ee7914e4a15e7b 100644 (file)
@@ -328,7 +328,7 @@ int verify_cs_pair(context, p_client_str, p_client, service, hostname,
     krb5_ticket        * ticket = NULL;
     krb5_keyblock      * keyblock = NULL;
     krb5_auth_context    auth_context = NULL;
-    krb5_data            request_data;
+    krb5_data            request_data = empty_data();
     char               * sname;
     float                dt;
 
@@ -355,27 +355,22 @@ int verify_cs_pair(context, p_client_str, p_client, service, hostname,
     /* obtain ticket & session key */
     if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) {
        com_err(prog, retval, "while getting client princ for %s", hostname);
-       krb5_free_cred_contents(context, &creds);
        return retval;
     }
 
     if ((retval = krb5_get_credentials(context, 0,
                                       ccache, &creds, &credsp))) {
        com_err(prog, retval, "while getting creds for %s", hostname);
-       krb5_free_cred_contents(context, &creds);
        return retval;
     }
 
-    krb5_free_cred_contents(context, &creds);
-
     if (do_timer)
        swatch_on();
 
     if ((retval = krb5_mk_req_extended(context, &auth_context, 0, NULL,
                                    credsp, &request_data))) {
        com_err(prog, retval, "while preparing AP_REQ for %s", hostname);
-        krb5_auth_con_free(context, auth_context);
-       return retval;
+       goto cleanup;
     }
 
     krb5_auth_con_free(context, auth_context);
@@ -385,24 +380,23 @@ int verify_cs_pair(context, p_client_str, p_client, service, hostname,
     if ((retval = get_server_key(context, credsp->server,
                                credsp->keyblock.enctype, &keyblock))) {
        com_err(prog, retval, "while getting server key for %s", hostname);
-       goto cleanup_rdata;
+       goto cleanup;
     }
 
     if (krb5_auth_con_init(context, &auth_context)) {
        com_err(prog, retval, "while creating auth_context for %s", hostname);
-       goto cleanup_keyblock;
+       goto cleanup;
     }
 
     if (krb5_auth_con_setuseruserkey(context, auth_context, keyblock)) {
        com_err(prog, retval, "while setting auth_context key %s", hostname);
-       goto cleanup_keyblock;
+       goto cleanup;
     }
 
     if ((retval = krb5_rd_req(context, &auth_context, &request_data,
                             NULL /* server */, 0, NULL, &ticket))) {
        com_err(prog, retval, "while decoding AP_REQ for %s", hostname);
-        krb5_auth_con_free(context, auth_context);
-       goto cleanup_keyblock;
+       goto cleanup;
     }
 
     if (do_timer) {
@@ -415,8 +409,6 @@ int verify_cs_pair(context, p_client_str, p_client, service, hostname,
            tgs_req_times.ht_min = dt;
     }
 
-    krb5_auth_con_free(context, auth_context);
-
     if (!(krb5_principal_compare(context,ticket->enc_part2->client,p_client))){
        char *returned_client;
         if ((retval = krb5_unparse_name(context, ticket->enc_part2->client,
@@ -431,14 +423,13 @@ int verify_cs_pair(context, p_client_str, p_client, service, hostname,
        retval = 0;
     }
 
+cleanup:
+    krb5_free_cred_contents(context, &creds);
     krb5_free_ticket(context, ticket);
-
-cleanup_keyblock:
+    krb5_auth_con_free(context, auth_context);
     krb5_free_keyblock(context, keyblock);
-
-cleanup_rdata:
     krb5_free_data_contents(context, &request_data);
-    if(credsp ) krb5_free_creds(context, credsp);
+    krb5_free_creds(context, credsp);
 
     return retval;
 }
index 1065191e2fa74624fb779e818e024d7ef8caa018..f90f8ac51ce30e4ce1afedfda4adca63205bfa08 100644 (file)
@@ -467,7 +467,14 @@ def _match_cmdnum(cmdnum, ind):
 # Return an environment suitable for running programs in the build
 # tree.  It is safe to modify the result.
 def _build_env():
-    return dict(runenv.env)
+    global buildtop
+    env = os.environ.copy()
+    for (k, v) in runenv.env.iteritems():
+        if v.find('./') == 0:
+            env[k] = os.path.join(buildtop, v)
+        else:
+            env[k] = v
+    return env
 
 # Merge the nested dictionaries cfg1 and cfg2 into a new dictionary.
 # cfg1 or cfg2 may be None, in which case the other is returned.  If
index fa7b36ebf8881e40e9752ba10c5aa517cd87a325..4e9225407a7a840b6f2e520dd8e45a1cdbcd1792 100644 (file)
@@ -268,6 +268,8 @@ krb5int_open_plugin (const char *filepath, struct plugin_file_handle **h, struct
             handle = dlopen(filepath, PLUGIN_DLOPEN_FLAGS);
             if (handle == NULL) {
                 const char *e = dlerror();
+                if (e == NULL)
+                    e = "unknown failure";
                 Tprintf ("dlopen(%s): %s\n", filepath, e);
                 err = ENOENT; /* XXX */
                 krb5int_set_error (ep, err, "%s", e);
@@ -335,6 +337,8 @@ krb5int_get_plugin_sym (struct plugin_file_handle *h,
         sym = dlsym (h->dlhandle, csymname);
         if (sym == NULL) {
             const char *e = dlerror (); /* XXX copy and save away */
+            if (e == NULL)
+                e = "unknown failure";
             Tprintf ("dlsym(%s): %s\n", csymname, e);
             err = ENOENT; /* XXX */
             krb5int_set_error(ep, err, "%s", e);