2 * Copyright (c) 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "kadmin_locl.h"
37 #include <gssapi_krb5.h>
38 #include <gssapi_spnego.h>
44 krb5_errx(dcontext, 1, "Failed (%d) on %s:%d", \
45 __r, __FILE__, __LINE__); \
49 static krb5_context dcontext;
51 #define INSIST(x) CHECK(!(x))
53 #define VERSION2 0x12345702
55 #define LAST_FRAGMENT 0x80000000
58 #define KADM_SERVER 2112
61 #define FLAVOR_GSS_VERSION 1
74 struct opaque_auth cred;
75 struct opaque_auth verf;
81 RPG_CONTINUE_INIT = 2,
91 krb5_ui_4 api_version;
108 parse_name(const unsigned char *p, size_t len,
109 const gss_OID oid, char **name)
117 if (memcmp(p, "\x04\x01", 2) != 0)
123 l = (p[0] << 8) | p[1];
126 if (l < 2 || len < l)
130 if (p[0] != 6 || p[1] != l - 2)
137 if (l != oid->length || memcmp(p, oid->elements, oid->length) != 0)
145 l = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
153 *name = malloc(l + 1);
154 INSIST(*name != NULL);
164 gss_error(krb5_context context,
165 gss_OID mech, OM_uint32 type, OM_uint32 error)
168 OM_uint32 msg_ctx = 0;
169 gss_buffer_desc status_string;
173 ret = gss_display_status (&new_stat,
179 krb5_warnx(context, "%.*s",
180 (int)status_string.length,
181 (char *)status_string.value);
182 gss_release_buffer (&new_stat, &status_string);
183 } while (!GSS_ERROR(ret) && msg_ctx != 0);
187 gss_print_errors (krb5_context context,
188 OM_uint32 maj_stat, OM_uint32 min_stat)
190 gss_error(context, GSS_C_NO_OID, GSS_C_GSS_CODE, maj_stat);
191 gss_error(context, GSS_C_NO_OID, GSS_C_MECH_CODE, min_stat);
195 read_data(krb5_storage *sp, krb5_storage *msg, size_t len)
203 if (tlen > sizeof(buf))
206 slen = krb5_storage_read(sp, buf, tlen);
207 INSIST(slen == tlen);
209 slen = krb5_storage_write(msg, buf, tlen);
210 INSIST(slen == tlen);
218 collect_framents(krb5_storage *sp, krb5_storage *msg)
223 size_t total_len = 0;
226 ret = krb5_ret_uint32(sp, &len);
230 last_fragment = (len & LAST_FRAGMENT);
231 len &= ~LAST_FRAGMENT;
233 CHECK(read_data(sp, msg, len));
236 } while(!last_fragment || total_len == 0);
241 static krb5_error_code
242 store_data_xdr(krb5_storage *sp, krb5_data data)
247 ret = krb5_store_data(sp, data);
250 res = 4 - (data.length % 4);
252 static const char zero[4] = { 0, 0, 0, 0 };
254 ret = krb5_storage_write(sp, zero, res);
256 return (ret < 0)? errno : krb5_storage_get_eof_code(sp);
261 static krb5_error_code
262 ret_data_xdr(krb5_storage *sp, krb5_data *data)
265 ret = krb5_ret_data(sp, data);
269 if ((data->length % 4) != 0) {
273 res = 4 - (data->length % 4);
275 ret = krb5_storage_read(sp, buf, res);
277 return (ret < 0)? errno : krb5_storage_get_eof_code(sp);
283 static krb5_error_code
284 ret_auth_opaque(krb5_storage *msg, struct opaque_auth *ao)
287 ret = krb5_ret_uint32(msg, &ao->flavor);
289 ret = ret_data_xdr(msg, &ao->data);
294 ret_gcred(krb5_data *data, struct gcred *gcred)
298 memset(gcred, 0, sizeof(*gcred));
300 sp = krb5_storage_from_data(data);
303 CHECK(krb5_ret_uint32(sp, &gcred->version));
304 CHECK(krb5_ret_uint32(sp, &gcred->proc));
305 CHECK(krb5_ret_uint32(sp, &gcred->seq_num));
306 CHECK(krb5_ret_uint32(sp, &gcred->service));
307 CHECK(ret_data_xdr(sp, &gcred->handle));
309 krb5_storage_free(sp);
314 static krb5_error_code
315 store_gss_init_res(krb5_storage *sp, krb5_data handle,
316 OM_uint32 maj_stat, OM_uint32 min_stat,
317 uint32_t seq_window, gss_buffer_t gout)
322 out.data = gout->value;
323 out.length = gout->length;
325 ret = store_data_xdr(sp, handle);
327 ret = krb5_store_uint32(sp, maj_stat);
329 ret = krb5_store_uint32(sp, min_stat);
331 ret = store_data_xdr(sp, out);
336 store_string_xdr(krb5_storage *sp, const char *str)
340 c.data = rk_UNCONST(str);
341 c.length = strlen(str) + 1;
345 return store_data_xdr(sp, c);
349 ret_string_xdr(krb5_storage *sp, char **str)
353 CHECK(ret_data_xdr(sp, &c));
355 *str = malloc(c.length + 1);
356 INSIST(*str != NULL);
357 memcpy(*str, c.data, c.length);
358 (*str)[c.length] = '\0';
365 store_principal_xdr(krb5_context context,
370 CHECK(krb5_unparse_name(context, p, &str));
371 CHECK(store_string_xdr(sp, str));
377 ret_principal_xdr(krb5_context context,
383 CHECK(ret_string_xdr(sp, &str));
385 CHECK(krb5_parse_name(context, str, p));
392 store_principal_ent(krb5_context context,
394 kadm5_principal_ent_rec *ent)
398 CHECK(store_principal_xdr(context, sp, ent->principal));
399 CHECK(krb5_store_uint32(sp, ent->princ_expire_time));
400 CHECK(krb5_store_uint32(sp, ent->pw_expiration));
401 CHECK(krb5_store_uint32(sp, ent->last_pwd_change));
402 CHECK(krb5_store_uint32(sp, ent->max_life));
403 CHECK(krb5_store_int32(sp, ent->mod_name == NULL));
405 CHECK(store_principal_xdr(context, sp, ent->mod_name));
406 CHECK(krb5_store_uint32(sp, ent->mod_date));
407 CHECK(krb5_store_uint32(sp, ent->attributes));
408 CHECK(krb5_store_uint32(sp, ent->kvno));
409 CHECK(krb5_store_uint32(sp, ent->mkvno));
410 CHECK(store_string_xdr(sp, ent->policy));
411 CHECK(krb5_store_int32(sp, ent->aux_attributes));
412 CHECK(krb5_store_int32(sp, ent->max_renewable_life));
413 CHECK(krb5_store_int32(sp, ent->last_success));
414 CHECK(krb5_store_int32(sp, ent->last_failed));
415 CHECK(krb5_store_int32(sp, ent->fail_auth_count));
416 CHECK(krb5_store_int32(sp, ent->n_key_data));
417 CHECK(krb5_store_int32(sp, ent->n_tl_data));
418 CHECK(krb5_store_int32(sp, ent->n_tl_data == 0));
419 if (ent->n_tl_data) {
422 for (tp = ent->tl_data; tp; tp = tp->tl_data_next) {
424 c.length = tp->tl_data_length;
425 c.data = tp->tl_data_contents;
427 CHECK(krb5_store_int32(sp, 0)); /* last item */
428 CHECK(krb5_store_int32(sp, tp->tl_data_type));
429 CHECK(store_data_xdr(sp, c));
431 CHECK(krb5_store_int32(sp, 1)); /* last item */
434 CHECK(krb5_store_int32(sp, ent->n_key_data));
435 for (i = 0; i < ent->n_key_data; i++) {
436 CHECK(krb5_store_uint32(sp, 2));
437 CHECK(krb5_store_uint32(sp, ent->kvno));
438 CHECK(krb5_store_uint32(sp, ent->key_data[i].key_data_type[0]));
439 CHECK(krb5_store_uint32(sp, ent->key_data[i].key_data_type[1]));
446 ret_principal_ent(krb5_context context,
448 kadm5_principal_ent_rec *ent)
453 memset(ent, 0, sizeof(*ent));
455 CHECK(ret_principal_xdr(context, sp, &ent->principal));
456 CHECK(krb5_ret_uint32(sp, &flag));
457 ent->princ_expire_time = flag;
458 CHECK(krb5_ret_uint32(sp, &flag));
459 ent->pw_expiration = flag;
460 CHECK(krb5_ret_uint32(sp, &flag));
461 ent->last_pwd_change = flag;
462 CHECK(krb5_ret_uint32(sp, &flag));
463 ent->max_life = flag;
464 CHECK(krb5_ret_uint32(sp, &flag));
466 ret_principal_xdr(context, sp, &ent->mod_name);
467 CHECK(krb5_ret_uint32(sp, &flag));
468 ent->mod_date = flag;
469 CHECK(krb5_ret_uint32(sp, &flag));
470 ent->attributes = flag;
471 CHECK(krb5_ret_uint32(sp, &flag));
473 CHECK(krb5_ret_uint32(sp, &flag));
475 CHECK(ret_string_xdr(sp, &ent->policy));
476 CHECK(krb5_ret_uint32(sp, &flag));
477 ent->aux_attributes = flag;
478 CHECK(krb5_ret_uint32(sp, &flag));
479 ent->max_renewable_life = flag;
480 CHECK(krb5_ret_uint32(sp, &flag));
481 ent->last_success = flag;
482 CHECK(krb5_ret_uint32(sp, &flag));
483 ent->last_failed = flag;
484 CHECK(krb5_ret_uint32(sp, &flag));
485 ent->fail_auth_count = flag;
486 CHECK(krb5_ret_uint32(sp, &flag));
487 ent->n_key_data = flag;
488 CHECK(krb5_ret_uint32(sp, &flag));
489 ent->n_tl_data = flag;
490 CHECK(krb5_ret_uint32(sp, &flag));
492 krb5_tl_data **tp = &ent->tl_data;
497 CHECK(krb5_ret_uint32(sp, &flag)); /* last item */
500 *tp = calloc(1, sizeof(**tp));
502 CHECK(krb5_ret_uint32(sp, &flag));
503 (*tp)->tl_data_type = flag;
504 CHECK(ret_data_xdr(sp, &c));
505 (*tp)->tl_data_length = c.length;
506 (*tp)->tl_data_contents = c.data;
507 tp = &(*tp)->tl_data_next;
511 INSIST(ent->n_tl_data == count);
513 INSIST(ent->n_tl_data == 0);
516 CHECK(krb5_ret_uint32(sp, &num));
517 INSIST(num == ent->n_key_data);
519 ent->key_data = calloc(num, sizeof(ent->key_data[0]));
520 INSIST(ent->key_data != NULL);
522 for (i = 0; i < num; i++) {
523 CHECK(krb5_ret_uint32(sp, &flag)); /* data version */
525 CHECK(krb5_ret_uint32(sp, &flag));
527 CHECK(krb5_ret_uint32(sp, &flag));
528 ent->key_data[i].key_data_type[0] = flag;
529 CHECK(krb5_ret_uint32(sp, &flag));
530 ent->key_data[i].key_data_type[1] = flag;
541 proc_create_principal(kadm5_server_context *context,
545 uint32_t version, mask;
546 kadm5_principal_ent_rec ent;
550 memset(&ent, 0, sizeof(ent));
552 CHECK(krb5_ret_uint32(in, &version));
553 INSIST(version == VERSION2);
554 CHECK(ret_principal_ent(context->context, in, &ent));
555 CHECK(krb5_ret_uint32(in, &mask));
556 CHECK(ret_string_xdr(in, &password));
558 INSIST(ent.principal);
561 ret = _kadm5_acl_check_permission(context, KADM5_PRIV_ADD, ent.principal);
565 ret = kadm5_create_principal(context, &ent, mask, password);
568 krb5_warn(context->context, ret, "create principal");
569 CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
570 CHECK(krb5_store_uint32(out, ret)); /* code */
573 kadm5_free_principal_ent(context, &ent);
577 proc_delete_principal(kadm5_server_context *context,
582 krb5_principal princ;
585 CHECK(krb5_ret_uint32(in, &version));
586 INSIST(version == VERSION2);
587 CHECK(ret_principal_xdr(context->context, in, &princ));
589 ret = _kadm5_acl_check_permission(context, KADM5_PRIV_DELETE, princ);
593 ret = kadm5_delete_principal(context, princ);
596 krb5_warn(context->context, ret, "delete principal");
597 CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
598 CHECK(krb5_store_uint32(out, ret)); /* code */
600 krb5_free_principal(context->context, princ);
604 proc_get_principal(kadm5_server_context *context,
608 uint32_t version, mask;
609 krb5_principal princ;
610 kadm5_principal_ent_rec ent;
613 memset(&ent, 0, sizeof(ent));
615 CHECK(krb5_ret_uint32(in, &version));
616 INSIST(version == VERSION2);
617 CHECK(ret_principal_xdr(context->context, in, &princ));
618 CHECK(krb5_ret_uint32(in, &mask));
620 ret = _kadm5_acl_check_permission(context, KADM5_PRIV_GET, princ);
624 ret = kadm5_get_principal(context, princ, &ent, mask);
627 krb5_warn(context->context, ret, "get principal principal");
629 CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
630 CHECK(krb5_store_uint32(out, ret)); /* code */
632 CHECK(store_principal_ent(context->context, out, &ent));
634 krb5_free_principal(context->context, princ);
635 kadm5_free_principal_ent(context, &ent);
639 proc_chrand_principal_v2(kadm5_server_context *context,
644 krb5_principal princ;
646 krb5_keyblock *new_keys;
649 CHECK(krb5_ret_uint32(in, &version));
650 INSIST(version == VERSION2);
651 CHECK(ret_principal_xdr(context->context, in, &princ));
653 ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ);
657 ret = kadm5_randkey_principal(context, princ,
661 krb5_warn(context->context, ret, "rand key principal");
663 CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
664 CHECK(krb5_store_uint32(out, ret));
667 CHECK(krb5_store_int32(out, n_keys));
669 for(i = 0; i < n_keys; i++){
670 CHECK(krb5_store_uint32(out, new_keys[i].keytype));
671 CHECK(store_data_xdr(out, new_keys[i].keyvalue));
672 krb5_free_keyblock_contents(context->context, &new_keys[i]);
676 krb5_free_principal(context->context, princ);
680 proc_init(kadm5_server_context *context,
684 CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
685 CHECK(krb5_store_uint32(out, 0)); /* code */
686 CHECK(krb5_store_uint32(out, 0)); /* code */
691 void (*func)(kadm5_server_context *, krb5_storage *, krb5_storage *);
694 { "create principal", proc_create_principal },
695 { "delete principal", proc_delete_principal },
696 { "modify principal", NULL },
697 { "rename principal", NULL },
698 { "get principal", proc_get_principal },
699 { "chpass principal", NULL },
700 { "chrand principal", proc_chrand_principal_v2 },
701 { "create policy", NULL },
702 { "delete policy", NULL },
703 { "modify policy", NULL },
704 { "get policy", NULL },
705 { "get privs", NULL },
706 { "init", proc_init },
707 { "get principals", NULL },
708 { "get polices", NULL },
709 { "setkey principal", NULL },
710 { "setkey principal v4", NULL },
711 { "create principal v3", NULL },
712 { "chpass principal v3", NULL },
713 { "chrand principal v3", NULL },
714 { "setkey principal v3", NULL }
717 static krb5_error_code
718 copyheader(krb5_storage *sp, krb5_data *data)
723 off = krb5_storage_seek(sp, 0, SEEK_CUR);
725 CHECK(krb5_data_alloc(data, off));
726 INSIST(off == data->length);
727 krb5_storage_seek(sp, 0, SEEK_SET);
728 sret = krb5_storage_read(sp, data->data, data->length);
730 INSIST(off == krb5_storage_seek(sp, 0, SEEK_CUR));
744 process_stream(krb5_context context,
745 unsigned char *buf, size_t ilen,
749 krb5_storage *msg, *reply, *dreply;
750 OM_uint32 maj_stat, min_stat;
751 gss_buffer_desc gin, gout;
753 void *server_handle = NULL;
755 memset(&gctx, 0, sizeof(gctx));
757 msg = krb5_storage_emem();
758 reply = krb5_storage_emem();
759 dreply = krb5_storage_emem();
762 * First packet comes partly from the caller
768 struct call_header chdr;
771 krb5_data headercopy;
773 krb5_storage_truncate(dreply, 0);
774 krb5_storage_truncate(reply, 0);
775 krb5_storage_truncate(msg, 0);
777 krb5_data_zero(&headercopy);
778 memset(&chdr, 0, sizeof(chdr));
779 memset(&gcred, 0, sizeof(gcred));
782 * This is very icky to handle the the auto-detection between
783 * the Heimdal protocol and the MIT ONC-RPC based protocol.
790 unsigned char tmp[4];
793 memcpy(tmp, buf, ilen);
794 slen = krb5_storage_read(sp, tmp + ilen, sizeof(tmp) - ilen);
795 INSIST(slen == sizeof(tmp) - ilen);
802 _krb5_get_int(buf, &len, 4);
803 last_fragment = (len & LAST_FRAGMENT) != 0;
804 len &= ~LAST_FRAGMENT;
811 slen = krb5_storage_write(msg, buf, len);
816 slen = krb5_storage_write(msg, buf, ilen);
817 INSIST(slen == ilen);
822 CHECK(read_data(sp, msg, len));
824 if (!last_fragment) {
825 ret = collect_framents(sp, msg);
826 if (ret == HEIM_ERR_EOF)
827 krb5_errx(context, 0, "client disconnected");
832 ret = collect_framents(sp, msg);
833 if (ret == HEIM_ERR_EOF)
834 krb5_errx(context, 0, "client disconnected");
837 krb5_storage_seek(msg, 0, SEEK_SET);
839 CHECK(krb5_ret_uint32(msg, &chdr.xid));
840 CHECK(krb5_ret_uint32(msg, &mtype));
841 CHECK(krb5_ret_uint32(msg, &chdr.rpcvers));
842 CHECK(krb5_ret_uint32(msg, &chdr.prog));
843 CHECK(krb5_ret_uint32(msg, &chdr.vers));
844 CHECK(krb5_ret_uint32(msg, &chdr.proc));
845 CHECK(ret_auth_opaque(msg, &chdr.cred));
846 CHECK(copyheader(msg, &headercopy));
847 CHECK(ret_auth_opaque(msg, &chdr.verf));
849 INSIST(chdr.rpcvers == RPC_VERSION);
850 INSIST(chdr.prog == KADM_SERVER);
851 INSIST(chdr.vers == VVERSION);
852 INSIST(chdr.cred.flavor == FLAVOR_GSS);
854 CHECK(ret_gcred(&chdr.cred.data, &gcred));
856 INSIST(gcred.version == FLAVOR_GSS_VERSION);
859 INSIST(chdr.verf.flavor == FLAVOR_GSS);
861 /* from first byte to last of credential */
862 gin.value = headercopy.data;
863 gin.length = headercopy.length;
864 gout.value = chdr.verf.data.data;
865 gout.length = chdr.verf.data.length;
867 maj_stat = gss_verify_mic(&min_stat, gctx.ctx, &gin, &gout, NULL);
868 INSIST(maj_stat == GSS_S_COMPLETE);
878 INSIST(gcred.service == rpg_privacy);
882 INSIST(krb5_data_cmp(&gcred.handle, &gctx.handle) == 0);
884 CHECK(ret_data_xdr(msg, &data));
886 gin.value = data.data;
887 gin.length = data.length;
889 maj_stat = gss_unwrap(&min_stat, gctx.ctx, &gin, &gout,
891 krb5_data_free(&data);
892 INSIST(maj_stat == GSS_S_COMPLETE);
893 INSIST(conf_state != 0);
895 sp = krb5_storage_from_mem(gout.value, gout.length);
898 CHECK(krb5_ret_uint32(sp, &seq));
899 INSIST (seq == gcred.seq_num);
902 * Check sequence number
904 INSIST(seq > gctx.seq_num);
908 * If context is setup, priv data have the seq_num stored
909 * first in the block, so add it here before users data is
912 CHECK(krb5_store_uint32(dreply, gctx.seq_num));
914 if (chdr.proc >= sizeof(procs)/sizeof(procs[0])) {
915 krb5_warnx(context, "proc number out of array");
916 } else if (procs[chdr.proc].func == NULL) {
917 krb5_warnx(context, "proc '%s' never implemented",
918 procs[chdr.proc].name);
920 krb5_warnx(context, "proc %s", procs[chdr.proc].name);
921 INSIST(server_handle != NULL);
922 (*procs[chdr.proc].func)(server_handle, sp, dreply);
924 krb5_storage_free(sp);
925 gss_release_buffer(&min_stat, &gout);
930 INSIST(gctx.inprogress == 0);
931 INSIST(gctx.ctx == NULL);
935 case RPG_CONTINUE_INIT: {
936 gss_name_t src_name = GSS_C_NO_NAME;
939 INSIST(gctx.inprogress);
941 CHECK(ret_data_xdr(msg, &in));
944 gin.length = in.length;
948 maj_stat = gss_accept_sec_context(&min_stat,
952 GSS_C_NO_CHANNEL_BINDINGS,
959 if (GSS_ERROR(maj_stat)) {
960 gss_print_errors(context, maj_stat, min_stat);
961 krb5_errx(context, 1, "gss error, exit");
963 if ((maj_stat & GSS_S_CONTINUE_NEEDED) == 0) {
964 kadm5_config_params realm_params;
970 memset(&realm_params, 0, sizeof(realm_params));
972 maj_stat = gss_export_name(&min_stat, src_name, &buf);
973 INSIST(maj_stat == GSS_S_COMPLETE);
975 CHECK(parse_name(buf.value, buf.length,
976 GSS_KRB5_MECHANISM, &client));
978 gss_release_buffer(&min_stat, &buf);
980 krb5_warnx(context, "%s connected", client);
982 ret = kadm5_s_init_with_password_ctx(context,
992 INSIST(gctx.ctx != GSS_C_NO_CONTEXT);
994 CHECK(krb5_store_uint32(dreply, 0));
995 CHECK(store_gss_init_res(dreply, gctx.handle,
996 maj_stat, min_stat, 1, &gout));
998 gss_release_buffer(&min_stat, &gout);
1000 gss_release_name(&min_stat, &src_name);
1005 krb5_errx(context, 1, "client destroyed gss context");
1007 krb5_errx(context, 1, "client sent unknown gsscode %d",
1011 krb5_data_free(&gcred.handle);
1012 krb5_data_free(&chdr.cred.data);
1013 krb5_data_free(&chdr.verf.data);
1014 krb5_data_free(&headercopy);
1016 CHECK(krb5_store_uint32(reply, chdr.xid));
1017 CHECK(krb5_store_uint32(reply, 1)); /* REPLY */
1018 CHECK(krb5_store_uint32(reply, 0)); /* MSG_ACCEPTED */
1023 CHECK(krb5_store_uint32(reply, 0)); /* flavor_none */
1024 CHECK(krb5_store_uint32(reply, 0)); /* length */
1026 CHECK(krb5_store_uint32(reply, 0)); /* SUCCESS */
1028 CHECK(krb5_storage_to_data(dreply, &data));
1029 INSIST(krb5_storage_write(reply, data.data, data.length) == data.length);
1030 krb5_data_free(&data);
1033 uint32_t seqnum = htonl(gctx.seq_num);
1036 gin.value = &seqnum;
1037 gin.length = sizeof(seqnum);
1039 maj_stat = gss_get_mic(&min_stat, gctx.ctx, 0, &gin, &gout);
1040 INSIST(maj_stat == GSS_S_COMPLETE);
1042 data.data = gout.value;
1043 data.length = gout.length;
1045 CHECK(krb5_store_uint32(reply, FLAVOR_GSS));
1046 CHECK(store_data_xdr(reply, data));
1047 gss_release_buffer(&min_stat, &gout);
1049 CHECK(krb5_store_uint32(reply, 0)); /* SUCCESS */
1051 CHECK(krb5_storage_to_data(dreply, &data));
1053 if (gctx.inprogress) {
1055 gctx.inprogress = 0;
1056 sret = krb5_storage_write(reply, data.data, data.length);
1057 INSIST(sret == data.length);
1058 krb5_data_free(&data);
1062 gin.value = data.data;
1063 gin.length = data.length;
1065 maj_stat = gss_wrap(&min_stat, gctx.ctx, 1, 0,
1066 &gin, &conf_state, &gout);
1067 INSIST(maj_stat == GSS_S_COMPLETE);
1068 INSIST(conf_state != 0);
1069 krb5_data_free(&data);
1071 data.data = gout.value;
1072 data.length = gout.length;
1074 store_data_xdr(reply, data);
1075 gss_release_buffer(&min_stat, &gout);
1082 CHECK(krb5_storage_to_data(reply, &data));
1083 CHECK(krb5_store_uint32(sp, data.length | LAST_FRAGMENT));
1084 sret = krb5_storage_write(sp, data.data, data.length);
1085 INSIST(sret == data.length);
1086 krb5_data_free(&data);
1094 handle_mit(krb5_context context, void *buf, size_t len, krb5_socket_t sock)
1100 sp = krb5_storage_from_fd(sock);
1103 process_stream(context, buf, len, sp);