2 * Copyright (c) 1999 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 KTH nor the names of its contributors may be
18 * used to endorse or promote products derived from this software without
19 * specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
33 #include "kadmin_locl.h"
34 #include <krb5-private.h>
36 #define Principal krb4_Principal
37 #define kadm_get krb4_kadm_get
44 RCSID("$Id: version4.c,v 1.16 1999/11/25 22:32:47 assar Exp $");
46 #define KADM_NO_OPCODE -1
47 #define KADM_NO_ENCRYPT -2
50 * make an error packet if we fail encrypting
54 make_you_loose_packet(int code, krb5_data *reply)
56 krb5_data_alloc(reply, KADM_VERSIZE + 4);
57 memcpy(reply->data, KADM_ULOSE, KADM_VERSIZE);
58 _krb5_put_int((char*)reply->data + KADM_VERSIZE, code, 4);
62 ret_fields(krb5_storage *sp, char *fields)
64 return sp->fetch(sp, fields, FLDSZ);
68 store_fields(krb5_storage *sp, char *fields)
70 return sp->store(sp, fields, FLDSZ);
74 ret_vals(krb5_storage *sp, Kadm_vals *vals)
79 memset(vals, 0, sizeof(*vals));
81 ret_fields(sp, vals->fields);
83 for(field = 31; field >= 0; field--) {
84 if(IS_FIELD(field, vals->fields)) {
87 krb5_ret_stringz(sp, &tmp_string);
88 strlcpy(vals->name, tmp_string, sizeof(vals->name));
92 krb5_ret_stringz(sp, &tmp_string);
93 strlcpy(vals->instance, tmp_string,
94 sizeof(vals->instance));
98 krb5_ret_int32(sp, &vals->exp_date);
101 krb5_ret_int16(sp, &vals->attributes);
104 krb5_ret_int8(sp, &vals->max_life);
107 krb5_ret_int32(sp, &vals->key_high);
108 krb5_ret_int32(sp, &vals->key_low);
112 krb5_ret_int32(sp, &vals->mod_date);
115 krb5_ret_stringz(sp, &tmp_string);
116 strlcpy(vals->mod_name, tmp_string,
117 sizeof(vals->mod_name));
121 krb5_ret_stringz(sp, &tmp_string);
122 strlcpy(vals->mod_instance, tmp_string,
123 sizeof(vals->mod_instance));
127 krb5_ret_int8(sp, &vals->key_version);
138 store_vals(krb5_storage *sp, Kadm_vals *vals)
142 store_fields(sp, vals->fields);
144 for(field = 31; field >= 0; field--) {
145 if(IS_FIELD(field, vals->fields)) {
148 krb5_store_stringz(sp, vals->name);
151 krb5_store_stringz(sp, vals->instance);
154 krb5_store_int32(sp, vals->exp_date);
157 krb5_store_int16(sp, vals->attributes);
160 krb5_store_int8(sp, vals->max_life);
163 krb5_store_int32(sp, vals->key_high);
164 krb5_store_int32(sp, vals->key_low);
168 krb5_store_int32(sp, vals->mod_date);
171 krb5_store_stringz(sp, vals->mod_name);
174 krb5_store_stringz(sp, vals->mod_instance);
177 krb5_store_int8(sp, vals->key_version);
188 flags_4_to_5(char *flags)
192 for(i = 31; i >= 0; i--) {
193 if(IS_FIELD(i, flags))
197 mask |= KADM5_PRINCIPAL;
199 mask |= KADM5_PW_EXPIRATION;
201 mask |= KADM5_MAX_LIFE;
204 mask |= KADM5_KEY_DATA;
206 mask |= KADM5_MOD_TIME;
209 mask |= KADM5_MOD_NAME;
217 ent_to_values(krb5_context context,
218 kadm5_principal_ent_t ent,
223 char realm[REALM_SZ];
225 memset(vals, 0, sizeof(*vals));
226 if(mask & KADM5_PRINCIPAL) {
227 ret = krb5_524_conv_principal(context, ent->principal,
228 vals->name, vals->instance, realm);
229 SET_FIELD(KADM_NAME, vals->fields);
230 SET_FIELD(KADM_INST, vals->fields);
232 if(mask & KADM5_PW_EXPIRATION) {
234 if(ent->princ_expire_time != 0)
235 exp = ent->princ_expire_time;
236 if(ent->pw_expiration != 0 && (exp == 0 || exp > ent->pw_expiration))
237 exp = ent->pw_expiration;
239 vals->exp_date = exp;
240 SET_FIELD(KADM_EXPDATE, vals->fields);
243 if(mask & KADM5_MAX_LIFE) {
244 if(ent->max_life == 0)
245 vals->max_life = 255;
247 vals->max_life = krb_time_to_life(0, ent->max_life);
248 SET_FIELD(KADM_MAXLIFE, vals->fields);
250 if(mask & KADM5_KEY_DATA) {
251 if(ent->n_key_data > 0) {
253 vals->key_version = ent->key_data[0].key_data_kvno;
254 SET_FIELD(KADM_KVNO, vals->fields);
257 /* XXX the key itself? */
260 if(mask & KADM5_MOD_TIME) {
261 vals->mod_date = ent->mod_date;
262 SET_FIELD(KADM_MODDATE, vals->fields);
264 if(mask & KADM5_MOD_NAME) {
265 krb5_524_conv_principal(context, ent->mod_name,
266 vals->mod_name, vals->mod_instance, realm);
267 SET_FIELD(KADM_MODNAME, vals->fields);
268 SET_FIELD(KADM_MODINST, vals->fields);
274 * convert the kadm4 values in `vals' to `ent' (and `mask')
277 static krb5_error_code
278 values_to_ent(krb5_context context,
280 kadm5_principal_ent_t ent,
285 memset(ent, 0, sizeof(*ent));
287 if(IS_FIELD(KADM_NAME, vals->fields)) {
289 if(IS_FIELD(KADM_INST, vals->fields))
290 inst = vals->instance;
291 ret = krb5_425_conv_principal(context,
298 *mask |= KADM5_PRINCIPAL;
300 if(IS_FIELD(KADM_EXPDATE, vals->fields)) {
301 ent->pw_expiration = vals->exp_date;
302 *mask |= KADM5_PW_EXPIRATION;
304 if(IS_FIELD(KADM_MAXLIFE, vals->fields)) {
305 ent->max_life = krb_life_to_time(0, vals->max_life);
306 *mask |= KADM5_MAX_LIFE;
309 if(IS_FIELD(KADM_DESKEY, vals->fields)) {
311 ent->key_data = calloc(3, sizeof(*ent->key_data));
312 if(ent->key_data == NULL)
314 for(i = 0; i < 3; i++) {
315 u_int32_t key_low, key_high;
317 ent->key_data[i].key_data_ver = 2;
319 if(IS_FIELD(KADM_KVNO, vals->fields))
320 ent->key_data[i].key_data_kvno = vals->key_version;
322 ent->key_data[i].key_data_type[0] = ETYPE_DES_CBC_MD5;
323 ent->key_data[i].key_data_length[0] = 8;
324 if((ent->key_data[i].key_data_contents[0] = malloc(8)) == NULL)
327 key_low = ntohl(vals->key_low);
328 key_high = ntohl(vals->key_high);
329 memcpy(ent->key_data[i].key_data_contents[0],
331 memcpy((char*)ent->key_data[i].key_data_contents[0] + 4,
333 ent->key_data[i].key_data_type[1] = KRB5_PW_SALT;
334 ent->key_data[i].key_data_length[1] = 0;
335 ent->key_data[i].key_data_contents[1] = NULL;
337 ent->key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4;
338 ent->key_data[2].key_data_type[0] = ETYPE_DES_CBC_CRC;
340 *mask |= KADM5_KEY_DATA;
344 if(IS_FIELD(KADM_MODDATE, vals->fields)) {
345 ent->mod_date = vals->mod_date;
346 *mask |= KADM5_MOD_TIME;
348 if(IS_FIELD(KADM_MODNAME, vals->fields)) {
350 if(IS_FIELD(KADM_MODINST, vals->fields))
351 inst = vals->mod_instance;
352 ret = krb5_425_conv_principal(context,
359 *mask |= KADM5_MOD_NAME;
366 * Try to translate a KADM5 error code into a v4 kadmin one.
376 case KADM5_AUTH_GET :
377 case KADM5_AUTH_ADD :
378 case KADM5_AUTH_MODIFY :
379 case KADM5_AUTH_DELETE :
380 case KADM5_AUTH_INSUFFICIENT :
383 return KADM_UK_RERROR;
386 case KADM5_RPC_ERROR :
389 case KADM5_NOT_INIT :
391 case KADM5_UNK_PRINC :
393 case KADM5_PASS_Q_TOOSHORT :
394 #ifdef KADM_PASS_Q_TOOSHORT
395 return KADM_PASS_Q_TOOSHORT;
397 return KADM_INSECURE_PW;
399 case KADM5_PASS_Q_CLASS :
400 #ifdef KADM_PASS_Q_CLASS
401 return KADM_PASS_Q_CLASS;
403 return KADM_INSECURE_PW;
405 case KADM5_PASS_Q_DICT :
406 #ifdef KADM_PASS_Q_DICT
407 return KADM_PASS_Q_DICT;
409 return KADM_INSECURE_PW;
411 case KADM5_PASS_REUSE :
412 case KADM5_PASS_TOOSOON :
413 case KADM5_BAD_PASSWORD :
414 return KADM_INSECURE_PW;
415 case KADM5_PROTECT_PRINCIPAL :
416 return KADM_IMMUTABLE;
417 case KADM5_POLICY_REF :
419 case KADM5_BAD_HIST_KEY :
420 case KADM5_UNK_POLICY :
421 case KADM5_BAD_MASK :
422 case KADM5_BAD_CLASS :
423 case KADM5_BAD_LENGTH :
424 case KADM5_BAD_POLICY :
425 case KADM5_BAD_PRINCIPAL :
426 case KADM5_BAD_AUX_ATTR :
427 case KADM5_BAD_HISTORY :
428 case KADM5_BAD_MIN_PASS_LIFE :
429 case KADM5_BAD_SERVER_HANDLE :
430 case KADM5_BAD_STRUCT_VERSION :
431 case KADM5_OLD_STRUCT_VERSION :
432 case KADM5_NEW_STRUCT_VERSION :
433 case KADM5_BAD_API_VERSION :
434 case KADM5_OLD_LIB_API_VERSION :
435 case KADM5_OLD_SERVER_API_VERSION :
436 case KADM5_NEW_LIB_API_VERSION :
437 case KADM5_NEW_SERVER_API_VERSION :
438 case KADM5_SECURE_PRINC_MISSING :
439 case KADM5_NO_RENAME_SALT :
440 case KADM5_BAD_CLIENT_PARAMS :
441 case KADM5_BAD_SERVER_PARAMS :
442 case KADM5_AUTH_LIST :
443 case KADM5_AUTH_CHANGEPW :
444 case KADM5_BAD_TL_TYPE :
445 case KADM5_MISSING_CONF_PARAMS :
446 case KADM5_BAD_SERVER_NAME :
448 return KADM_UNAUTH; /* XXX */
457 kadm_ser_cpw(krb5_context context,
459 krb5_principal principal,
460 const char *principal_string,
461 krb5_storage *message,
465 char *password = NULL;
468 krb5_warnx(context, "v4-compat %s: cpw %s",
469 principal_string, principal_string);
471 ret = message->fetch(message, key + 4, 4);
472 ret = message->fetch(message, key, 4);
473 ret = krb5_ret_stringz(message, &password);
479 pwd_data.data = password;
480 pwd_data.length = strlen(password);
482 tmp = kadm5_check_password_quality (context, principal, &pwd_data);
485 krb5_store_stringz (reply, (char *)tmp);
486 ret = KADM5_PASS_Q_DICT;
489 ret = kadm5_chpass_principal(kadm_handle, principal, password);
491 krb5_key_data key_data[3];
493 for(i = 0; i < 3; i++) {
494 key_data[i].key_data_ver = 2;
495 key_data[i].key_data_kvno = 0;
497 key_data[i].key_data_type[0] = ETYPE_DES_CBC_CRC;
498 key_data[i].key_data_length[0] = 8;
499 key_data[i].key_data_contents[0] = malloc(8);
500 memcpy(key_data[i].key_data_contents[0], &key, 8);
502 key_data[i].key_data_type[1] = KRB5_PW_SALT;
503 key_data[i].key_data_length[1] = 0;
504 key_data[i].key_data_contents[1] = NULL;
506 key_data[0].key_data_type[0] = ETYPE_DES_CBC_MD5;
507 key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4;
508 ret = kadm5_s_chpass_principal_with_key(kadm_handle,
509 principal, 3, key_data);
513 krb5_store_stringz(reply, (char*)krb5_get_err_text(context, ret));
518 krb5_warn(context, ret, "v4-compat cpw");
519 return error_code(ret);
523 kadm_ser_add(krb5_context context,
525 krb5_principal principal,
526 const char *principal_string,
527 krb5_storage *message,
531 kadm5_principal_ent_rec ent, out;
536 ret_vals(message, &values);
538 ret = values_to_ent(context, &values, &ent, &mask);
542 krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
543 krb5_warnx(context, "v4-compat %s: add %s",
544 principal_string, name);
546 ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_ADD);
550 ret = kadm5_s_create_principal_with_key(kadm_handle, &ent, mask);
552 kadm5_free_principal_ent(kadm_handle, &ent);
556 mask = KADM5_PRINCIPAL | KADM5_PW_EXPIRATION | KADM5_MAX_LIFE |
557 KADM5_KEY_DATA | KADM5_MOD_TIME | KADM5_MOD_NAME;
559 kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
560 ent_to_values(context, &out, mask, &values);
561 kadm5_free_principal_ent(kadm_handle, &ent);
562 kadm5_free_principal_ent(kadm_handle, &out);
563 store_vals(reply, &values);
566 krb5_warn(context, ret, "v4-compat add");
567 return error_code(ret);
571 kadm_ser_get(krb5_context context,
573 krb5_principal principal,
574 const char *principal_string,
575 krb5_storage *message,
580 kadm5_principal_ent_rec ent, out;
585 ret_vals(message, &values);
586 /* XXX BRAIN DAMAGE! these flags are not stored in the same order
588 krb5_ret_int8(message, &flags[3]);
589 krb5_ret_int8(message, &flags[2]);
590 krb5_ret_int8(message, &flags[1]);
591 krb5_ret_int8(message, &flags[0]);
592 ret = values_to_ent(context, &values, &ent, &mask);
596 krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
597 krb5_warnx(context, "v4-compat %s: get %s",
598 principal_string, name);
600 ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_GET);
604 mask = flags_4_to_5(flags);
606 ret = kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
607 kadm5_free_principal_ent(kadm_handle, &ent);
612 ent_to_values(context, &out, mask, &values);
614 kadm5_free_principal_ent(kadm_handle, &out);
616 store_vals(reply, &values);
619 krb5_warn(context, ret, "v4-compat get");
620 return error_code(ret);
624 kadm_ser_mod(krb5_context context,
626 krb5_principal principal,
627 const char *principal_string,
628 krb5_storage *message,
631 Kadm_vals values1, values2;
632 kadm5_principal_ent_rec ent, out;
637 ret_vals(message, &values1);
638 /* why are the old values sent? is the mask the same in the old and
640 ret_vals(message, &values2);
642 ret = values_to_ent(context, &values2, &ent, &mask);
646 krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
647 krb5_warnx(context, "v4-compat %s: mod %s",
648 principal_string, name);
650 ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_MODIFY);
654 ret = kadm5_s_modify_principal(kadm_handle, &ent, mask);
656 kadm5_free_principal_ent(kadm_handle, &ent);
657 krb5_warn(context, ret, "kadm5_s_modify_principal");
661 ret = kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
663 kadm5_free_principal_ent(kadm_handle, &ent);
664 krb5_warn(context, ret, "kadm5_s_modify_principal");
668 ent_to_values(context, &out, mask, &values1);
670 kadm5_free_principal_ent(kadm_handle, &ent);
671 kadm5_free_principal_ent(kadm_handle, &out);
673 store_vals(reply, &values1);
676 krb5_warn(context, ret, "v4-compat mod");
677 return error_code(ret);
681 kadm_ser_del(krb5_context context,
683 krb5_principal principal,
684 const char *principal_string,
685 krb5_storage *message,
689 kadm5_principal_ent_rec ent;
694 ret_vals(message, &values);
696 ret = values_to_ent(context, &values, &ent, &mask);
700 krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
701 krb5_warnx(context, "v4-compat %s: del %s",
702 principal_string, name);
704 ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_DELETE);
708 ret = kadm5_delete_principal(kadm_handle, ent.principal);
710 kadm5_free_principal_ent(kadm_handle, &ent);
717 krb5_warn(context, ret, "v4-compat add");
718 return error_code(ret);
722 dispatch(krb5_context context,
724 krb5_principal principal,
725 const char *principal_string,
731 krb5_storage *sp_in, *sp_out;
733 sp_in = krb5_storage_from_data(&msg);
734 krb5_ret_int8(sp_in, &command);
736 sp_out = krb5_storage_emem();
737 sp_out->store(sp_out, KADM_VERSTR, KADM_VERSIZE);
738 krb5_store_int32(sp_out, 0);
742 retval = kadm_ser_cpw(context, kadm_handle, principal,
747 retval = kadm_ser_add(context, kadm_handle, principal,
752 retval = kadm_ser_get(context, kadm_handle, principal,
757 retval = kadm_ser_mod(context, kadm_handle, principal,
762 retval = kadm_ser_del(context, kadm_handle, principal,
767 krb5_warnx(context, "v4-compat %s: unknown opcode: %d",
768 principal_string, command);
769 retval = KADM_NO_OPCODE;
772 krb5_storage_free(sp_in);
774 sp_out->seek(sp_out, KADM_VERSIZE, SEEK_SET);
775 krb5_store_int32(sp_out, retval);
777 krb5_storage_to_data(sp_out, reply);
778 krb5_storage_free(sp_out);
783 * Decode a v4 kadmin packet in `message' and create a reply in `reply'
787 decode_packet(krb5_context context,
788 struct sockaddr_in *admin_addr,
789 struct sockaddr_in *client_addr,
799 char sname[] = "changepw", sinst[] = "kerberos";
800 unsigned long checksum;
801 des_key_schedule schedule;
802 char *msg = message.data;
804 krb5_principal client;
807 if(message.length < KADM_VERSIZE
808 || strncmp(msg, KADM_VERSTR, KADM_VERSIZE) != 0) {
809 make_you_loose_packet (KADM_BAD_VER, reply);
814 off += _krb5_get_int(msg + off, &rlen, 4);
815 memset(&authent, 0, sizeof(authent));
816 authent.length = message.length - rlen - KADM_VERSIZE - 4;
817 memcpy(authent.dat, (char*)msg + off, authent.length);
818 off += authent.length;
821 krb5_principal principal;
824 ret = krb5_make_principal(context, &principal, NULL,
825 "changepw", "kerberos", NULL);
827 krb5_warn (context, ret, "krb5_make_principal");
828 make_you_loose_packet (KADM_NOMEM, reply);
831 ret = krb5_kt_read_service_key(context,
835 /* ETYPE_DES_CBC_CRC,*/
838 krb5_free_principal(context, principal);
840 if(ret == KRB5_KT_NOTFOUND)
841 make_you_loose_packet(KADM_NO_AUTH, reply);
844 make_you_loose_packet(KADM_NO_AUTH, reply);
845 krb5_warn(context, ret, "krb5_kt_read_service_key");
849 if(key->keyvalue.length != 8)
850 krb5_abortx(context, "key has wrong length (%lu)",
851 (unsigned long)key->keyvalue.length);
852 krb_set_key(key->keyvalue.data, 0);
853 krb5_free_keyblock(context, key);
856 ret = krb_rd_req(&authent, sname, sinst,
857 client_addr->sin_addr.s_addr, &ad, NULL);
860 make_you_loose_packet(krb_err_base + ret, reply);
861 krb5_warnx(context, "krb_rd_req: %d", ret);
865 krb5_425_conv_principal(context, ad.pname, ad.pinst, ad.prealm,
867 krb5_unparse_name(context, client, &client_str);
869 ret = kadm5_init_with_password_ctx(context,
876 krb5_warn (context, ret, "kadm5_init_with_password_ctx");
877 make_you_loose_packet (KADM_NOMEM, reply);
881 checksum = des_quad_cksum((des_cblock*)(msg + off), NULL, rlen,
883 if(checksum != ad.checksum) {
884 krb5_warnx(context, "decode_packet: bad checksum");
885 make_you_loose_packet (KADM_BAD_CHK, reply);
888 des_set_key(&ad.session, schedule);
889 ret = krb_rd_priv(msg + off, rlen, schedule, &ad.session,
890 client_addr, admin_addr, &msg_dat);
892 make_you_loose_packet (krb_err_base + ret, reply);
893 krb5_warnx(context, "krb_rd_priv: %d", ret);
901 d.data = msg_dat.app_data;
902 d.length = msg_dat.app_length;
904 retval = dispatch(context, kadm_handle,
905 client, client_str, d, &r);
906 krb5_data_alloc(reply, r.length + 26);
907 reply->length = krb_mk_priv(r.data, reply->data, r.length,
908 schedule, &ad.session,
909 admin_addr, client_addr);
910 if((ssize_t)reply->length < 0) {
911 make_you_loose_packet(KADM_NO_ENCRYPT, reply);
916 krb5_free_principal(context, client);
921 handle_v4(krb5_context context,
926 struct sockaddr_in admin_addr, client_addr;
928 krb5_data message, reply;
931 addr_len = sizeof(client_addr);
932 if (getsockname(fd, (struct sockaddr*)&admin_addr, &addr_len) < 0)
933 krb5_errx (context, 1, "getsockname");
934 addr_len = sizeof(client_addr);
935 if (getpeername(fd, (struct sockaddr*)&client_addr, &addr_len) < 0)
936 krb5_errx (context, 1, "getpeername");
940 /* first time around, we have already read len, and two
941 bytes of the version string */
942 krb5_data_alloc(&message, len);
943 memcpy(message.data, "KA", 2);
944 n = krb5_net_read(context, &fd, (char*)message.data + 2,
949 krb5_err (context, 1, errno, "krb5_net_read");
956 n = krb5_net_read(context, &fd, buf, sizeof(2));
960 krb5_err (context, 1, errno, "krb5_net_read");
961 _krb5_get_int(buf, &tmp, 2);
962 krb5_data_alloc(&message, tmp);
963 n = krb5_net_read(context, &fd, message.data, message.length);
965 krb5_errx (context, 1, "EOF in krb5_net_read");
967 krb5_err (context, 1, errno, "krb5_net_read");
969 decode_packet(context, &admin_addr, &client_addr,
971 krb5_data_free(&message);
975 _krb5_put_int(buf, reply.length, sizeof(buf));
976 n = krb5_net_write(context, &fd, buf, sizeof(buf));
978 krb5_err (context, 1, errno, "krb5_net_write");
979 n = krb5_net_write(context, &fd, reply.data, reply.length);
981 krb5_err (context, 1, errno, "krb5_net_write");
982 krb5_data_free(&reply);