/* ** choice operator; optimizations: ** charset / charset => charset ** true / x => true, x / false => x, false / x => x ** (x / true is not equivalent to true) */ static int lp_choice (lua_State *L) { Charset st1, st2; TTree *t1 = getpatt(L, 1, NULL); TTree *t2 = getpatt(L, 2, NULL); if (tocharset(t1, &st1) && tocharset(t2, &st2)) { TTree *t = newcharset(L); loopset(i, treebuffer(t)[i] = st1.cs[i] | st2.cs[i]); } else if (nofail(t1) || t2->tag == TFalse) lua_pushvalue(L, 1); /* true / x => true, x / false => x */ else if (t1->tag == TFalse) lua_pushvalue(L, 2); /* false / x => x */ else newroot2sib(L, TChoice); return 1; }
krb5_error_code KRB5_CALLCONV krb5_verify_init_creds(krb5_context context, krb5_creds *creds, krb5_principal server_arg, krb5_keytab keytab_arg, krb5_ccache *ccache_arg, krb5_verify_init_creds_opt *options) { krb5_error_code ret; krb5_principal server; krb5_keytab keytab; krb5_ccache ccache; krb5_keytab_entry kte; krb5_creds in_creds, *out_creds; krb5_auth_context authcon; krb5_data ap_req; /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */ server = NULL; keytab = NULL; ccache = NULL; out_creds = NULL; authcon = NULL; ap_req.data = NULL; if (keytab_arg) { keytab = keytab_arg; } else { if ((ret = krb5_kt_default(context, &keytab))) goto cleanup; } if (server_arg) { ret = krb5_copy_principal(context, server_arg, &server); if (ret) goto cleanup; } else { /* Use a principal name from the keytab. */ ret = k5_kt_get_principal(context, keytab, &server); if (ret) { /* There's no keytab, or it's empty, or we can't read it. * Allow this unless configuration demands verification. */ if (!nofail(context, options, creds)) ret = 0; goto cleanup; } } /* first, check if the server is in the keytab. If not, there's no reason to continue. rd_req does all this, but there's no way to know that a given error is caused by a missing keytab or key, and not by some other problem. */ if (krb5_is_referral_realm(&server->realm)) { krb5_free_data_contents(context, &server->realm); ret = krb5_get_default_realm(context, &server->realm.data); if (ret) goto cleanup; server->realm.length = strlen(server->realm.data); } if ((ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte))) { /* this means there is no keying material. This is ok, as long as it is not prohibited by the configuration */ if (!nofail(context, options, creds)) ret = 0; goto cleanup; } krb5_kt_free_entry(context, &kte); /* If the creds are for the server principal, we're set, just do a mk_req. * Otherwise, do a get_credentials first. */ if (krb5_principal_compare(context, server, creds->server)) { /* make an ap_req */ if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds, &ap_req))) goto cleanup; } else { /* this is unclean, but it's the easiest way without ripping the library into very small pieces. store the client's initial cred in a memory ccache, then call the library. Later, we'll copy everything except the initial cred into the ccache we return to the user. A clean implementation would involve library internals with a coherent idea of "in" and "out". */ /* insert the initial cred into the ccache */ if ((ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) { ccache = NULL; goto cleanup; } if ((ret = krb5_cc_initialize(context, ccache, creds->client))) goto cleanup; if ((ret = krb5_cc_store_cred(context, ccache, creds))) goto cleanup; /* set up for get_creds */ memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = creds->client; in_creds.server = server; if ((ret = krb5_timeofday(context, &in_creds.times.endtime))) goto cleanup; in_creds.times.endtime += 5*60; if ((ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds))) goto cleanup; /* make an ap_req */ if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds, &ap_req))) goto cleanup; } /* wipe the auth context for mk_req */ if (authcon) { krb5_auth_con_free(context, authcon); authcon = NULL; } /* verify the ap_req */ if ((ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab, NULL, NULL))) goto cleanup; /* if we get this far, then the verification succeeded. We can still fail if the library stuff here fails, but that's it */ if (ccache_arg && ccache) { if (*ccache_arg == NULL) { krb5_ccache retcc; retcc = NULL; if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) || (ret = krb5_cc_initialize(context, retcc, creds->client)) || (ret = copy_creds_except(context, ccache, retcc, creds->server))) { if (retcc) krb5_cc_destroy(context, retcc); } else { *ccache_arg = retcc; } } else { ret = copy_creds_except(context, ccache, *ccache_arg, server); } } /* if any of the above paths returned an errors, then ret is set accordingly. * Either that, or it's zero, which is fine, too */ cleanup: if ( server) krb5_free_principal(context, server); if (!keytab_arg && keytab) krb5_kt_close(context, keytab); if (ccache) krb5_cc_destroy(context, ccache); if (out_creds) krb5_free_creds(context, out_creds); if (authcon) krb5_auth_con_free(context, authcon); if (ap_req.data) free(ap_req.data); return(ret); }
krb5_error_code KRB5_CALLCONV krb5_verify_init_creds(krb5_context context, krb5_creds *creds, krb5_principal server, krb5_keytab keytab, krb5_ccache *ccache, krb5_verify_init_creds_opt *options) { krb5_error_code ret; krb5_principal *host_princs = NULL; krb5_keytab defkeytab = NULL; krb5_keytab_entry kte; krb5_boolean have_keys = FALSE; size_t i; if (keytab == NULL) { ret = krb5_kt_default(context, &defkeytab); if (ret) goto cleanup; keytab = defkeytab; } if (server != NULL) { /* Check if server exists in keytab first. */ ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte); if (ret) goto cleanup; krb5_kt_free_entry(context, &kte); have_keys = TRUE; ret = get_vfy_cred(context, creds, server, keytab, ccache); } else { /* Try using the host service principals from the keytab. */ if (keytab->ops->start_seq_get == NULL) { ret = EINVAL; goto cleanup; } ret = get_host_princs_from_keytab(context, keytab, &host_princs); if (ret) goto cleanup; if (host_princs == NULL) { ret = KRB5_KT_NOTFOUND; goto cleanup; } have_keys = TRUE; /* Try all host principals until one succeeds or they all fail. */ for (i = 0; host_princs[i] != NULL; i++) { ret = get_vfy_cred(context, creds, host_princs[i], keytab, ccache); if (ret == 0) break; } } cleanup: /* If we have no key to verify with, pretend to succeed unless * configuration directs otherwise. */ if (!have_keys && !nofail(context, options, creds)) ret = 0; if (defkeytab != NULL) krb5_kt_close(context, defkeytab); krb5_free_principal(context, server); free_princ_list(context, host_princs); return ret; }