00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <ctype.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025
00026 #include <isc/buffer.h>
00027 #include <isc/dir.h>
00028 #include <isc/entropy.h>
00029 #include <isc/file.h>
00030 #include <isc/lex.h>
00031 #include <isc/mem.h>
00032 #include <isc/once.h>
00033 #include <isc/print.h>
00034 #include <isc/platform.h>
00035 #include <isc/random.h>
00036 #include <isc/string.h>
00037 #include <isc/time.h>
00038 #include <isc/util.h>
00039
00040 #include <dns/fixedname.h>
00041 #include <dns/name.h>
00042 #include <dns/rdata.h>
00043 #include <dns/rdataclass.h>
00044 #include <dns/result.h>
00045 #include <dns/types.h>
00046 #include <dns/keyvalues.h>
00047 #include <dns/log.h>
00048
00049 #include <dst/gssapi.h>
00050 #include <dst/result.h>
00051
00052 #include "dst_internal.h"
00053
00054
00055
00056
00057
00058 #if defined(GSSAPI) && defined(USE_ISC_SPNEGO)
00059 #include "spnego.h"
00060 #define gss_accept_sec_context gss_accept_sec_context_spnego
00061 #define gss_init_sec_context gss_init_sec_context_spnego
00062 #endif
00063
00064
00065
00066
00067
00068
00069
00070
00071 #ifdef GSSAPI
00072 #ifdef WIN32
00073 #include <krb5/krb5.h>
00074 #else
00075 #include ISC_PLATFORM_KRB5HEADER
00076 #endif
00077
00078 static unsigned char krb5_mech_oid_bytes[] = {
00079 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
00080 };
00081
00082 #ifndef USE_ISC_SPNEGO
00083 static unsigned char spnego_mech_oid_bytes[] = {
00084 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
00085 };
00086 #endif
00087
00088 static gss_OID_desc mech_oid_set_array[] = {
00089 { sizeof(krb5_mech_oid_bytes), krb5_mech_oid_bytes },
00090 #ifndef USE_ISC_SPNEGO
00091 { sizeof(spnego_mech_oid_bytes), spnego_mech_oid_bytes },
00092 #endif
00093 };
00094
00095 static gss_OID_set_desc mech_oid_set = {
00096 sizeof(mech_oid_set_array) / sizeof(*mech_oid_set_array),
00097 mech_oid_set_array
00098 };
00099
00100 #endif
00101
00102 #define REGION_TO_GBUFFER(r, gb) \
00103 do { \
00104 (gb).length = (r).length; \
00105 (gb).value = (r).base; \
00106 } while (0)
00107
00108 #define GBUFFER_TO_REGION(gb, r) \
00109 do { \
00110 (r).length = (unsigned int)(gb).length; \
00111 (r).base = (gb).value; \
00112 } while (0)
00113
00114
00115 #define RETERR(x) do { \
00116 result = (x); \
00117 if (result != ISC_R_SUCCESS) \
00118 goto out; \
00119 } while (0)
00120
00121 #ifdef GSSAPI
00122 static inline void
00123 name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
00124 gss_buffer_desc *gbuffer)
00125 {
00126 dns_name_t tname, *namep;
00127 isc_region_t r;
00128 isc_result_t result;
00129
00130 if (!dns_name_isabsolute(name))
00131 namep = name;
00132 else
00133 {
00134 unsigned int labels;
00135 dns_name_init(&tname, NULL);
00136 labels = dns_name_countlabels(name);
00137 dns_name_getlabelsequence(name, 0, labels - 1, &tname);
00138 namep = &tname;
00139 }
00140
00141 result = dns_name_toprincipal(namep, buffer);
00142 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00143 isc_buffer_putuint8(buffer, 0);
00144 isc_buffer_usedregion(buffer, &r);
00145 REGION_TO_GBUFFER(r, *gbuffer);
00146 }
00147
00148 static void
00149 log_cred(const gss_cred_id_t cred) {
00150 OM_uint32 gret, minor, lifetime;
00151 gss_name_t gname;
00152 gss_buffer_desc gbuffer;
00153 gss_cred_usage_t usage;
00154 const char *usage_text;
00155 char buf[1024];
00156
00157 gret = gss_inquire_cred(&minor, cred, &gname, &lifetime, &usage, NULL);
00158 if (gret != GSS_S_COMPLETE) {
00159 gss_log(3, "failed gss_inquire_cred: %s",
00160 gss_error_tostring(gret, minor, buf, sizeof(buf)));
00161 return;
00162 }
00163
00164 gret = gss_display_name(&minor, gname, &gbuffer, NULL);
00165 if (gret != GSS_S_COMPLETE)
00166 gss_log(3, "failed gss_display_name: %s",
00167 gss_error_tostring(gret, minor, buf, sizeof(buf)));
00168 else {
00169 switch (usage) {
00170 case GSS_C_BOTH:
00171 usage_text = "GSS_C_BOTH";
00172 break;
00173 case GSS_C_INITIATE:
00174 usage_text = "GSS_C_INITIATE";
00175 break;
00176 case GSS_C_ACCEPT:
00177 usage_text = "GSS_C_ACCEPT";
00178 break;
00179 default:
00180 usage_text = "???";
00181 }
00182 gss_log(3, "gss cred: \"%s\", %s, %lu", (char *)gbuffer.value,
00183 usage_text, (unsigned long)lifetime);
00184 }
00185
00186 if (gret == GSS_S_COMPLETE) {
00187 if (gbuffer.length != 0U) {
00188 gret = gss_release_buffer(&minor, &gbuffer);
00189 if (gret != GSS_S_COMPLETE)
00190 gss_log(3, "failed gss_release_buffer: %s",
00191 gss_error_tostring(gret, minor, buf,
00192 sizeof(buf)));
00193 }
00194 }
00195
00196 gret = gss_release_name(&minor, &gname);
00197 if (gret != GSS_S_COMPLETE)
00198 gss_log(3, "failed gss_release_name: %s",
00199 gss_error_tostring(gret, minor, buf, sizeof(buf)));
00200 }
00201 #endif
00202
00203 #ifdef GSSAPI
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 static void
00216 check_config(const char *gss_name) {
00217 const char *p;
00218 krb5_context krb5_ctx;
00219 char *krb5_realm_name = NULL;
00220
00221 if (strncasecmp(gss_name, "DNS/", 4) != 0) {
00222 gss_log(ISC_LOG_ERROR, "tkey-gssapi-credential (%s) "
00223 "should start with 'DNS/'", gss_name);
00224 return;
00225 }
00226
00227 if (krb5_init_context(&krb5_ctx) != 0) {
00228 gss_log(ISC_LOG_ERROR, "Unable to initialise krb5 context");
00229 return;
00230 }
00231 if (krb5_get_default_realm(krb5_ctx, &krb5_realm_name) != 0) {
00232 gss_log(ISC_LOG_ERROR, "Unable to get krb5 default realm");
00233 krb5_free_context(krb5_ctx);
00234 return;
00235 }
00236 p = strchr(gss_name, '@');
00237 if (p == NULL) {
00238 gss_log(ISC_LOG_ERROR, "badly formatted "
00239 "tkey-gssapi-credentials (%s)", gss_name);
00240 krb5_free_context(krb5_ctx);
00241 return;
00242 }
00243 if (strcasecmp(p + 1, krb5_realm_name) != 0) {
00244 gss_log(ISC_LOG_ERROR, "default realm from krb5.conf (%s) "
00245 "does not match tkey-gssapi-credential (%s)",
00246 krb5_realm_name, gss_name);
00247 krb5_free_context(krb5_ctx);
00248 return;
00249 }
00250 krb5_free_context(krb5_ctx);
00251 }
00252 #endif
00253
00254 isc_result_t
00255 dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
00256 gss_cred_id_t *cred)
00257 {
00258 #ifdef GSSAPI
00259 isc_result_t result;
00260 isc_buffer_t namebuf;
00261 gss_name_t gname;
00262 gss_buffer_desc gnamebuf;
00263 unsigned char array[DNS_NAME_MAXTEXT + 1];
00264 OM_uint32 gret, minor;
00265 OM_uint32 lifetime;
00266 gss_cred_usage_t usage;
00267 char buf[1024];
00268
00269 REQUIRE(cred != NULL && *cred == NULL);
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 if (name != NULL) {
00281 isc_buffer_init(&namebuf, array, sizeof(array));
00282 name_to_gbuffer(name, &namebuf, &gnamebuf);
00283 gret = gss_import_name(&minor, &gnamebuf,
00284 GSS_C_NO_OID, &gname);
00285 if (gret != GSS_S_COMPLETE) {
00286 check_config((char *)array);
00287
00288 gss_log(3, "failed gss_import_name: %s",
00289 gss_error_tostring(gret, minor, buf,
00290 sizeof(buf)));
00291 return (ISC_R_FAILURE);
00292 }
00293 } else
00294 gname = NULL;
00295
00296
00297 if (gname != NULL)
00298 gss_log(3, "acquiring credentials for %s",
00299 (char *)gnamebuf.value);
00300 else {
00301
00302 gss_log(3, "acquiring credentials for ?");
00303 }
00304
00305 if (initiate)
00306 usage = GSS_C_INITIATE;
00307 else
00308 usage = GSS_C_ACCEPT;
00309
00310 gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE,
00311 &mech_oid_set, usage, cred, NULL, &lifetime);
00312
00313 if (gret != GSS_S_COMPLETE) {
00314 gss_log(3, "failed to acquire %s credentials for %s: %s",
00315 initiate ? "initiate" : "accept",
00316 (gname != NULL) ? (char *)gnamebuf.value : "?",
00317 gss_error_tostring(gret, minor, buf, sizeof(buf)));
00318 if (gname != NULL)
00319 check_config((char *)array);
00320 result = ISC_R_FAILURE;
00321 goto cleanup;
00322 }
00323
00324 gss_log(4, "acquired %s credentials for %s",
00325 initiate ? "initiate" : "accept",
00326 (gname != NULL) ? (char *)gnamebuf.value : "?");
00327
00328 log_cred(*cred);
00329 result = ISC_R_SUCCESS;
00330
00331 cleanup:
00332 if (gname != NULL) {
00333 gret = gss_release_name(&minor, &gname);
00334 if (gret != GSS_S_COMPLETE)
00335 gss_log(3, "failed gss_release_name: %s",
00336 gss_error_tostring(gret, minor, buf,
00337 sizeof(buf)));
00338 }
00339
00340 return (result);
00341 #else
00342 REQUIRE(cred != NULL && *cred == NULL);
00343
00344 UNUSED(name);
00345 UNUSED(initiate);
00346 UNUSED(cred);
00347
00348 return (ISC_R_NOTIMPLEMENTED);
00349 #endif
00350 }
00351
00352 isc_boolean_t
00353 dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
00354 dns_name_t *realm)
00355 {
00356 #ifdef GSSAPI
00357 char sbuf[DNS_NAME_FORMATSIZE];
00358 char nbuf[DNS_NAME_FORMATSIZE];
00359 char rbuf[DNS_NAME_FORMATSIZE];
00360 char *sname;
00361 char *rname;
00362 isc_buffer_t buffer;
00363 isc_result_t result;
00364
00365
00366
00367
00368
00369 isc_buffer_init(&buffer, sbuf, sizeof(sbuf));
00370 result = dns_name_toprincipal(signer, &buffer);
00371 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00372 isc_buffer_putuint8(&buffer, 0);
00373 if (name != NULL)
00374 dns_name_format(name, nbuf, sizeof(nbuf));
00375 dns_name_format(realm, rbuf, sizeof(rbuf));
00376
00377
00378
00379
00380
00381
00382 rname = strchr(sbuf, '@');
00383 if (rname == NULL)
00384 return (isc_boolean_false);
00385 *rname = '\0';
00386 rname++;
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 sname = strchr(sbuf, '/');
00397 if (sname == NULL)
00398 return (isc_boolean_false);
00399 *sname = '\0';
00400 sname++;
00401 if (strcmp(sbuf, "host") != 0)
00402 return (isc_boolean_false);
00403
00404
00405
00406
00407 if (name != NULL) {
00408 if ((strcasecmp(sname, nbuf) == 0)
00409 && (strcmp(rname, rbuf) == 0))
00410 return (isc_boolean_true);
00411 } else {
00412 if (strcmp(rname, rbuf) == 0)
00413 return (isc_boolean_true);
00414 }
00415
00416 return (isc_boolean_false);
00417 #else
00418 UNUSED(signer);
00419 UNUSED(name);
00420 UNUSED(realm);
00421 return (isc_boolean_false);
00422 #endif
00423 }
00424
00425 isc_boolean_t
00426 dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
00427 dns_name_t *realm)
00428 {
00429 #ifdef GSSAPI
00430 char sbuf[DNS_NAME_FORMATSIZE];
00431 char nbuf[DNS_NAME_FORMATSIZE];
00432 char rbuf[DNS_NAME_FORMATSIZE];
00433 char *sname;
00434 char *nname;
00435 char *rname;
00436 isc_buffer_t buffer;
00437 isc_result_t result;
00438
00439
00440
00441
00442
00443 isc_buffer_init(&buffer, sbuf, sizeof(sbuf));
00444 result = dns_name_toprincipal(signer, &buffer);
00445 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00446 isc_buffer_putuint8(&buffer, 0);
00447 if (name != NULL)
00448 dns_name_format(name, nbuf, sizeof(nbuf));
00449 dns_name_format(realm, rbuf, sizeof(rbuf));
00450
00451
00452
00453
00454
00455
00456 rname = strchr(sbuf, '@');
00457 if (rname == NULL)
00458 return (isc_boolean_false);
00459 sname = strchr(sbuf, '$');
00460 if (sname == NULL)
00461 return (isc_boolean_false);
00462
00463
00464
00465
00466 if (rname - sname != 1)
00467 return (isc_boolean_false);
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 rname++;
00479 *sname = '\0';
00480 sname = sbuf;
00481
00482
00483
00484
00485
00486 if (name != NULL) {
00487 nname = strchr(nbuf, '.');
00488 if (nname == NULL)
00489 return (isc_boolean_false);
00490 *nname++ = '\0';
00491 }
00492
00493
00494
00495
00496 if (name != NULL) {
00497 if ((strcasecmp(sname, nbuf) == 0)
00498 && (strcmp(rname, rbuf) == 0)
00499 && (strcasecmp(nname, rbuf) == 0))
00500 return (isc_boolean_true);
00501 } else {
00502 if (strcmp(rname, rbuf) == 0)
00503 return (isc_boolean_true);
00504 }
00505
00506
00507 return (isc_boolean_false);
00508 #else
00509 UNUSED(signer);
00510 UNUSED(name);
00511 UNUSED(realm);
00512 return (isc_boolean_false);
00513 #endif
00514 }
00515
00516 isc_result_t
00517 dst_gssapi_releasecred(gss_cred_id_t *cred) {
00518 #ifdef GSSAPI
00519 OM_uint32 gret, minor;
00520 char buf[1024];
00521
00522 REQUIRE(cred != NULL && *cred != NULL);
00523
00524 gret = gss_release_cred(&minor, cred);
00525 if (gret != GSS_S_COMPLETE) {
00526
00527 gss_log(3, "failed releasing credential: %s",
00528 gss_error_tostring(gret, minor, buf, sizeof(buf)));
00529 }
00530 *cred = NULL;
00531
00532 return(ISC_R_SUCCESS);
00533 #else
00534 UNUSED(cred);
00535
00536 return (ISC_R_NOTIMPLEMENTED);
00537 #endif
00538 }
00539
00540 #ifdef GSSAPI
00541
00542
00543
00544
00545
00546 static void
00547 gss_err_message(isc_mem_t *mctx, isc_uint32_t major, isc_uint32_t minor,
00548 char **err_message)
00549 {
00550 char buf[1024];
00551 char *estr;
00552
00553 if (err_message == NULL || mctx == NULL) {
00554
00555 return;
00556 }
00557
00558 estr = gss_error_tostring(major, minor, buf, sizeof(buf));
00559 if (estr != NULL)
00560 (*err_message) = isc_mem_strdup(mctx, estr);
00561 }
00562 #endif
00563
00564 isc_result_t
00565 dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
00566 isc_buffer_t *outtoken, gss_ctx_id_t *gssctx,
00567 isc_mem_t *mctx, char **err_message)
00568 {
00569 #ifdef GSSAPI
00570 isc_region_t r;
00571 isc_buffer_t namebuf;
00572 gss_name_t gname;
00573 OM_uint32 gret, minor, ret_flags, flags;
00574 gss_buffer_desc gintoken, *gintokenp, gouttoken = GSS_C_EMPTY_BUFFER;
00575 isc_result_t result;
00576 gss_buffer_desc gnamebuf;
00577 unsigned char array[DNS_NAME_MAXTEXT + 1];
00578
00579
00580 REQUIRE(gssctx != NULL);
00581 REQUIRE(mctx != NULL);
00582
00583 isc_buffer_init(&namebuf, array, sizeof(array));
00584 name_to_gbuffer(name, &namebuf, &gnamebuf);
00585
00586
00587 gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
00588 if (gret != GSS_S_COMPLETE) {
00589 gss_err_message(mctx, gret, minor, err_message);
00590 result = ISC_R_FAILURE;
00591 goto out;
00592 }
00593
00594 if (intoken != NULL) {
00595
00596 REGION_TO_GBUFFER(*intoken, gintoken);
00597 gintokenp = &gintoken;
00598 } else {
00599 gintokenp = NULL;
00600 }
00601
00602
00603
00604
00605
00606 flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG;
00607
00608 gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx,
00609 gname, GSS_SPNEGO_MECHANISM, flags,
00610 0, NULL, gintokenp,
00611 NULL, &gouttoken, &ret_flags, NULL);
00612
00613 if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
00614 gss_err_message(mctx, gret, minor, err_message);
00615 if (err_message != NULL && *err_message != NULL)
00616 gss_log(3, "Failure initiating security context: %s",
00617 *err_message);
00618 else
00619 gss_log(3, "Failure initiating security context");
00620
00621 result = ISC_R_FAILURE;
00622 goto out;
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 if (gouttoken.length != 0U) {
00634 GBUFFER_TO_REGION(gouttoken, r);
00635 RETERR(isc_buffer_copyregion(outtoken, &r));
00636 (void)gss_release_buffer(&minor, &gouttoken);
00637 }
00638
00639 if (gret == GSS_S_COMPLETE)
00640 result = ISC_R_SUCCESS;
00641 else
00642 result = DNS_R_CONTINUE;
00643
00644 out:
00645 (void)gss_release_name(&minor, &gname);
00646 return (result);
00647 #else
00648 UNUSED(name);
00649 UNUSED(intoken);
00650 UNUSED(outtoken);
00651 UNUSED(gssctx);
00652 UNUSED(mctx);
00653 UNUSED(err_message);
00654
00655 return (ISC_R_NOTIMPLEMENTED);
00656 #endif
00657 }
00658
00659 isc_result_t
00660 dst_gssapi_acceptctx(gss_cred_id_t cred,
00661 const char *gssapi_keytab,
00662 isc_region_t *intoken, isc_buffer_t **outtoken,
00663 gss_ctx_id_t *ctxout, dns_name_t *principal,
00664 isc_mem_t *mctx)
00665 {
00666 #ifdef GSSAPI
00667 isc_region_t r;
00668 isc_buffer_t namebuf;
00669 gss_buffer_desc gnamebuf = GSS_C_EMPTY_BUFFER, gintoken,
00670 gouttoken = GSS_C_EMPTY_BUFFER;
00671 OM_uint32 gret, minor;
00672 gss_ctx_id_t context = GSS_C_NO_CONTEXT;
00673 gss_name_t gname = NULL;
00674 isc_result_t result;
00675 char buf[1024];
00676
00677 REQUIRE(outtoken != NULL && *outtoken == NULL);
00678
00679 REGION_TO_GBUFFER(*intoken, gintoken);
00680
00681 if (*ctxout == NULL)
00682 context = GSS_C_NO_CONTEXT;
00683 else
00684 context = *ctxout;
00685
00686 if (gssapi_keytab != NULL) {
00687 #if defined(ISC_PLATFORM_GSSAPI_KRB5_HEADER) || defined(WIN32)
00688 gret = gsskrb5_register_acceptor_identity(gssapi_keytab);
00689 if (gret != GSS_S_COMPLETE) {
00690 gss_log(3, "failed "
00691 "gsskrb5_register_acceptor_identity(%s): %s",
00692 gssapi_keytab,
00693 gss_error_tostring(gret, 0, buf, sizeof(buf)));
00694 return (DNS_R_INVALIDTKEY);
00695 }
00696 #else
00697
00698
00699
00700
00701 const char *old = getenv("KRB5_KTNAME");
00702 if (old == NULL || strcmp(old, gssapi_keytab) != 0) {
00703 char *kt = malloc(strlen(gssapi_keytab) + 13);
00704 if (kt == NULL)
00705 return (ISC_R_NOMEMORY);
00706 sprintf(kt, "KRB5_KTNAME=%s", gssapi_keytab);
00707 if (putenv(kt) != 0)
00708 return (ISC_R_NOMEMORY);
00709 }
00710 #endif
00711 }
00712
00713 log_cred(cred);
00714
00715 gret = gss_accept_sec_context(&minor, &context, cred, &gintoken,
00716 GSS_C_NO_CHANNEL_BINDINGS, &gname,
00717 NULL, &gouttoken, NULL, NULL, NULL);
00718
00719 result = ISC_R_FAILURE;
00720
00721 switch (gret) {
00722 case GSS_S_COMPLETE:
00723 result = ISC_R_SUCCESS;
00724 break;
00725 case GSS_S_CONTINUE_NEEDED:
00726 result = DNS_R_CONTINUE;
00727 break;
00728 case GSS_S_DEFECTIVE_TOKEN:
00729 case GSS_S_DEFECTIVE_CREDENTIAL:
00730 case GSS_S_BAD_SIG:
00731 case GSS_S_DUPLICATE_TOKEN:
00732 case GSS_S_OLD_TOKEN:
00733 case GSS_S_NO_CRED:
00734 case GSS_S_CREDENTIALS_EXPIRED:
00735 case GSS_S_BAD_BINDINGS:
00736 case GSS_S_NO_CONTEXT:
00737 case GSS_S_BAD_MECH:
00738 case GSS_S_FAILURE:
00739 result = DNS_R_INVALIDTKEY;
00740
00741 default:
00742 gss_log(3, "failed gss_accept_sec_context: %s",
00743 gss_error_tostring(gret, minor, buf, sizeof(buf)));
00744 return (result);
00745 }
00746
00747 if (gouttoken.length > 0U) {
00748 RETERR(isc_buffer_allocate(mctx, outtoken,
00749 (unsigned int)gouttoken.length));
00750 GBUFFER_TO_REGION(gouttoken, r);
00751 RETERR(isc_buffer_copyregion(*outtoken, &r));
00752 (void)gss_release_buffer(&minor, &gouttoken);
00753 }
00754
00755 if (gret == GSS_S_COMPLETE) {
00756 gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
00757 if (gret != GSS_S_COMPLETE) {
00758 gss_log(3, "failed gss_display_name: %s",
00759 gss_error_tostring(gret, minor,
00760 buf, sizeof(buf)));
00761 RETERR(ISC_R_FAILURE);
00762 }
00763
00764
00765
00766
00767
00768
00769
00770 if (gnamebuf.length > 0U &&
00771 ((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
00772 gnamebuf.length--;
00773
00774 gss_log(3, "gss-api source name (accept) is %.*s",
00775 (int)gnamebuf.length, (char *)gnamebuf.value);
00776
00777 GBUFFER_TO_REGION(gnamebuf, r);
00778 isc_buffer_init(&namebuf, r.base, r.length);
00779 isc_buffer_add(&namebuf, r.length);
00780
00781 RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname,
00782 0, NULL));
00783
00784 if (gnamebuf.length != 0U) {
00785 gret = gss_release_buffer(&minor, &gnamebuf);
00786 if (gret != GSS_S_COMPLETE)
00787 gss_log(3, "failed gss_release_buffer: %s",
00788 gss_error_tostring(gret, minor, buf,
00789 sizeof(buf)));
00790 }
00791 }
00792
00793 *ctxout = context;
00794
00795 out:
00796 if (gname != NULL) {
00797 gret = gss_release_name(&minor, &gname);
00798 if (gret != GSS_S_COMPLETE)
00799 gss_log(3, "failed gss_release_name: %s",
00800 gss_error_tostring(gret, minor, buf,
00801 sizeof(buf)));
00802 }
00803
00804 return (result);
00805 #else
00806 UNUSED(cred);
00807 UNUSED(gssapi_keytab);
00808 UNUSED(intoken);
00809 UNUSED(outtoken);
00810 UNUSED(ctxout);
00811 UNUSED(principal);
00812 UNUSED(mctx);
00813
00814 return (ISC_R_NOTIMPLEMENTED);
00815 #endif
00816 }
00817
00818 isc_result_t
00819 dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx)
00820 {
00821 #ifdef GSSAPI
00822 OM_uint32 gret, minor;
00823 char buf[1024];
00824
00825 UNUSED(mctx);
00826
00827 REQUIRE(gssctx != NULL && *gssctx != NULL);
00828
00829
00830 gret = gss_delete_sec_context(&minor, gssctx, GSS_C_NO_BUFFER);
00831 if (gret != GSS_S_COMPLETE) {
00832
00833 gss_log(3, "Failure deleting security context %s",
00834 gss_error_tostring(gret, minor, buf, sizeof(buf)));
00835 }
00836 return(ISC_R_SUCCESS);
00837 #else
00838 UNUSED(mctx);
00839 UNUSED(gssctx);
00840 return (ISC_R_NOTIMPLEMENTED);
00841 #endif
00842 }
00843
00844 char *
00845 gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
00846 char *buf, size_t buflen) {
00847 #ifdef GSSAPI
00848 gss_buffer_desc msg_minor = GSS_C_EMPTY_BUFFER,
00849 msg_major = GSS_C_EMPTY_BUFFER;
00850 OM_uint32 msg_ctx, minor_stat;
00851
00852
00853 msg_ctx = 0;
00854 (void)gss_display_status(&minor_stat, major, GSS_C_GSS_CODE,
00855 GSS_C_NULL_OID, &msg_ctx, &msg_major);
00856
00857
00858 msg_ctx = 0;
00859 (void)gss_display_status(&minor_stat, minor, GSS_C_MECH_CODE,
00860 GSS_C_NULL_OID, &msg_ctx, &msg_minor);
00861
00862 snprintf(buf, buflen, "GSSAPI error: Major = %s, Minor = %s.",
00863 (char *)msg_major.value, (char *)msg_minor.value);
00864
00865 if (msg_major.length != 0U)
00866 (void)gss_release_buffer(&minor_stat, &msg_major);
00867 if (msg_minor.length != 0U)
00868 (void)gss_release_buffer(&minor_stat, &msg_minor);
00869 return(buf);
00870 #else
00871 snprintf(buf, buflen, "GSSAPI error: Major = %u, Minor = %u.",
00872 major, minor);
00873
00874 return (buf);
00875 #endif
00876 }
00877
00878 void
00879 gss_log(int level, const char *fmt, ...) {
00880 va_list ap;
00881
00882 va_start(ap, fmt);
00883 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00884 DNS_LOGMODULE_TKEY, ISC_LOG_DEBUG(level), fmt, ap);
00885 va_end(ap);
00886 }
00887
00888