2 * Copyright (c) 1999 - 2002 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.29.2.1 2004/04/29 12:29:23 lha 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_lose_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 krb5_storage_read(sp
, fields
, FLDSZ
);
68 store_fields(krb5_storage
*sp
, char *fields
)
70 return krb5_storage_write(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_PRINC_EXPIRE_TIME
;
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
];
226 memset(vals
, 0, sizeof(*vals
));
227 if(mask
& KADM5_PRINCIPAL
) {
228 ret
= krb5_524_conv_principal(context
, ent
->principal
,
229 vals
->name
, vals
->instance
, realm
);
230 SET_FIELD(KADM_NAME
, vals
->fields
);
231 SET_FIELD(KADM_INST
, vals
->fields
);
233 if(mask
& KADM5_PRINC_EXPIRE_TIME
) {
234 if(ent
->princ_expire_time
!= 0)
235 exp
= ent
->princ_expire_time
;
237 if(mask
& KADM5_PW_EXPIRATION
) {
238 if(ent
->pw_expiration
!= 0 && (exp
== 0 || exp
> ent
->pw_expiration
))
239 exp
= ent
->pw_expiration
;
242 vals
->exp_date
= exp
;
243 SET_FIELD(KADM_EXPDATE
, vals
->fields
);
245 if(mask
& KADM5_MAX_LIFE
) {
246 if(ent
->max_life
== 0)
247 vals
->max_life
= 255;
249 vals
->max_life
= krb_time_to_life(0, ent
->max_life
);
250 SET_FIELD(KADM_MAXLIFE
, vals
->fields
);
252 if(mask
& KADM5_KEY_DATA
) {
253 if(ent
->n_key_data
> 0) {
255 vals
->key_version
= ent
->key_data
[0].key_data_kvno
;
256 SET_FIELD(KADM_KVNO
, vals
->fields
);
259 /* XXX the key itself? */
262 if(mask
& KADM5_MOD_TIME
) {
263 vals
->mod_date
= ent
->mod_date
;
264 SET_FIELD(KADM_MODDATE
, vals
->fields
);
266 if(mask
& KADM5_MOD_NAME
) {
267 krb5_524_conv_principal(context
, ent
->mod_name
,
268 vals
->mod_name
, vals
->mod_instance
, realm
);
269 SET_FIELD(KADM_MODNAME
, vals
->fields
);
270 SET_FIELD(KADM_MODINST
, vals
->fields
);
276 * convert the kadm4 values in `vals' to `ent' (and `mask')
279 static krb5_error_code
280 values_to_ent(krb5_context context
,
282 kadm5_principal_ent_t ent
,
287 memset(ent
, 0, sizeof(*ent
));
289 if(IS_FIELD(KADM_NAME
, vals
->fields
)) {
291 if(IS_FIELD(KADM_INST
, vals
->fields
))
292 inst
= vals
->instance
;
293 ret
= krb5_425_conv_principal(context
,
300 *mask
|= KADM5_PRINCIPAL
;
302 if(IS_FIELD(KADM_EXPDATE
, vals
->fields
)) {
303 ent
->princ_expire_time
= vals
->exp_date
;
304 *mask
|= KADM5_PRINC_EXPIRE_TIME
;
306 if(IS_FIELD(KADM_MAXLIFE
, vals
->fields
)) {
307 ent
->max_life
= krb_life_to_time(0, vals
->max_life
);
308 *mask
|= KADM5_MAX_LIFE
;
311 if(IS_FIELD(KADM_DESKEY
, vals
->fields
)) {
313 ent
->key_data
= calloc(3, sizeof(*ent
->key_data
));
314 if(ent
->key_data
== NULL
)
316 for(i
= 0; i
< 3; i
++) {
317 u_int32_t key_low
, key_high
;
319 ent
->key_data
[i
].key_data_ver
= 2;
321 if(IS_FIELD(KADM_KVNO
, vals
->fields
))
322 ent
->key_data
[i
].key_data_kvno
= vals
->key_version
;
324 ent
->key_data
[i
].key_data_type
[0] = ETYPE_DES_CBC_MD5
;
325 ent
->key_data
[i
].key_data_length
[0] = 8;
326 if((ent
->key_data
[i
].key_data_contents
[0] = malloc(8)) == NULL
)
329 key_low
= ntohl(vals
->key_low
);
330 key_high
= ntohl(vals
->key_high
);
331 memcpy(ent
->key_data
[i
].key_data_contents
[0],
333 memcpy((char*)ent
->key_data
[i
].key_data_contents
[0] + 4,
335 ent
->key_data
[i
].key_data_type
[1] = KRB5_PW_SALT
;
336 ent
->key_data
[i
].key_data_length
[1] = 0;
337 ent
->key_data
[i
].key_data_contents
[1] = NULL
;
339 ent
->key_data
[1].key_data_type
[0] = ETYPE_DES_CBC_MD4
;
340 ent
->key_data
[2].key_data_type
[0] = ETYPE_DES_CBC_CRC
;
342 *mask
|= KADM5_KEY_DATA
;
346 if(IS_FIELD(KADM_MODDATE
, vals
->fields
)) {
347 ent
->mod_date
= vals
->mod_date
;
348 *mask
|= KADM5_MOD_TIME
;
350 if(IS_FIELD(KADM_MODNAME
, vals
->fields
)) {
352 if(IS_FIELD(KADM_MODINST
, vals
->fields
))
353 inst
= vals
->mod_instance
;
354 ret
= krb5_425_conv_principal(context
,
361 *mask
|= KADM5_MOD_NAME
;
368 * Try to translate a KADM5 error code into a v4 kadmin one.
378 case KADM5_AUTH_GET
:
379 case KADM5_AUTH_ADD
:
380 case KADM5_AUTH_MODIFY
:
381 case KADM5_AUTH_DELETE
:
382 case KADM5_AUTH_INSUFFICIENT
:
385 return KADM_UK_RERROR
;
388 case KADM5_RPC_ERROR
:
391 case KADM5_NOT_INIT
:
393 case KADM5_UNK_PRINC
:
395 case KADM5_PASS_Q_TOOSHORT
:
396 #ifdef KADM_PASS_Q_TOOSHORT
397 return KADM_PASS_Q_TOOSHORT
;
399 return KADM_INSECURE_PW
;
401 case KADM5_PASS_Q_CLASS
:
402 #ifdef KADM_PASS_Q_CLASS
403 return KADM_PASS_Q_CLASS
;
405 return KADM_INSECURE_PW
;
407 case KADM5_PASS_Q_DICT
:
408 #ifdef KADM_PASS_Q_DICT
409 return KADM_PASS_Q_DICT
;
411 return KADM_INSECURE_PW
;
413 case KADM5_PASS_REUSE
:
414 case KADM5_PASS_TOOSOON
:
415 case KADM5_BAD_PASSWORD
:
416 return KADM_INSECURE_PW
;
417 case KADM5_PROTECT_PRINCIPAL
:
418 return KADM_IMMUTABLE
;
419 case KADM5_POLICY_REF
:
421 case KADM5_BAD_HIST_KEY
:
422 case KADM5_UNK_POLICY
:
423 case KADM5_BAD_MASK
:
424 case KADM5_BAD_CLASS
:
425 case KADM5_BAD_LENGTH
:
426 case KADM5_BAD_POLICY
:
427 case KADM5_BAD_PRINCIPAL
:
428 case KADM5_BAD_AUX_ATTR
:
429 case KADM5_BAD_HISTORY
:
430 case KADM5_BAD_MIN_PASS_LIFE
:
431 case KADM5_BAD_SERVER_HANDLE
:
432 case KADM5_BAD_STRUCT_VERSION
:
433 case KADM5_OLD_STRUCT_VERSION
:
434 case KADM5_NEW_STRUCT_VERSION
:
435 case KADM5_BAD_API_VERSION
:
436 case KADM5_OLD_LIB_API_VERSION
:
437 case KADM5_OLD_SERVER_API_VERSION
:
438 case KADM5_NEW_LIB_API_VERSION
:
439 case KADM5_NEW_SERVER_API_VERSION
:
440 case KADM5_SECURE_PRINC_MISSING
:
441 case KADM5_NO_RENAME_SALT
:
442 case KADM5_BAD_CLIENT_PARAMS
:
443 case KADM5_BAD_SERVER_PARAMS
:
444 case KADM5_AUTH_LIST
:
445 case KADM5_AUTH_CHANGEPW
:
446 case KADM5_BAD_TL_TYPE
:
447 case KADM5_MISSING_CONF_PARAMS
:
448 case KADM5_BAD_SERVER_NAME
:
450 return KADM_UNAUTH
; /* XXX */
459 kadm_ser_cpw(krb5_context context
,
461 krb5_principal principal
,
462 const char *principal_string
,
463 krb5_storage
*message
,
467 char *password
= NULL
;
470 krb5_warnx(context
, "v4-compat %s: CHPASS %s",
471 principal_string
, principal_string
);
473 ret
= krb5_storage_read(message
, key
+ 4, 4);
474 ret
= krb5_storage_read(message
, key
, 4);
475 ret
= krb5_ret_stringz(message
, &password
);
481 pwd_data
.data
= password
;
482 pwd_data
.length
= strlen(password
);
484 tmp
= kadm5_check_password_quality (context
, principal
, &pwd_data
);
487 krb5_store_stringz (reply
, (char *)tmp
);
488 ret
= KADM5_PASS_Q_DICT
;
491 ret
= kadm5_chpass_principal(kadm_handle
, principal
, password
);
493 krb5_key_data key_data
[3];
495 for(i
= 0; i
< 3; i
++) {
496 key_data
[i
].key_data_ver
= 2;
497 key_data
[i
].key_data_kvno
= 0;
499 key_data
[i
].key_data_type
[0] = ETYPE_DES_CBC_CRC
;
500 key_data
[i
].key_data_length
[0] = 8;
501 key_data
[i
].key_data_contents
[0] = malloc(8);
502 memcpy(key_data
[i
].key_data_contents
[0], &key
, 8);
504 key_data
[i
].key_data_type
[1] = KRB5_PW_SALT
;
505 key_data
[i
].key_data_length
[1] = 0;
506 key_data
[i
].key_data_contents
[1] = NULL
;
508 key_data
[0].key_data_type
[0] = ETYPE_DES_CBC_MD5
;
509 key_data
[1].key_data_type
[0] = ETYPE_DES_CBC_MD4
;
510 ret
= kadm5_s_chpass_principal_with_key(kadm_handle
,
511 principal
, 3, key_data
);
515 krb5_store_stringz(reply
, (char*)krb5_get_err_text(context
, ret
));
520 krb5_warn(context
, ret
, "v4-compat CHPASS");
521 return error_code(ret
);
525 kadm_ser_add(krb5_context context
,
527 krb5_principal principal
,
528 const char *principal_string
,
529 krb5_storage
*message
,
533 kadm5_principal_ent_rec ent
, out
;
538 ret_vals(message
, &values
);
540 ret
= values_to_ent(context
, &values
, &ent
, &mask
);
544 krb5_unparse_name_fixed(context
, ent
.principal
, name
, sizeof(name
));
545 krb5_warnx(context
, "v4-compat %s: ADD %s",
546 principal_string
, name
);
548 ret
= _kadm5_acl_check_permission (kadm_handle
, KADM5_PRIV_ADD
,
553 ret
= kadm5_s_create_principal_with_key(kadm_handle
, &ent
, mask
);
555 kadm5_free_principal_ent(kadm_handle
, &ent
);
559 mask
= KADM5_PRINCIPAL
| KADM5_PRINC_EXPIRE_TIME
| KADM5_MAX_LIFE
|
560 KADM5_KEY_DATA
| KADM5_MOD_TIME
| KADM5_MOD_NAME
;
562 kadm5_get_principal(kadm_handle
, ent
.principal
, &out
, mask
);
563 ent_to_values(context
, &out
, mask
, &values
);
564 kadm5_free_principal_ent(kadm_handle
, &ent
);
565 kadm5_free_principal_ent(kadm_handle
, &out
);
566 store_vals(reply
, &values
);
569 krb5_warn(context
, ret
, "v4-compat ADD");
570 return error_code(ret
);
574 kadm_ser_get(krb5_context context
,
576 krb5_principal principal
,
577 const char *principal_string
,
578 krb5_storage
*message
,
583 kadm5_principal_ent_rec ent
, out
;
588 ret_vals(message
, &values
);
589 /* XXX BRAIN DAMAGE! these flags are not stored in the same order
591 krb5_ret_int8(message
, &flags
[3]);
592 krb5_ret_int8(message
, &flags
[2]);
593 krb5_ret_int8(message
, &flags
[1]);
594 krb5_ret_int8(message
, &flags
[0]);
595 ret
= values_to_ent(context
, &values
, &ent
, &mask
);
599 krb5_unparse_name_fixed(context
, ent
.principal
, name
, sizeof(name
));
600 krb5_warnx(context
, "v4-compat %s: GET %s",
601 principal_string
, name
);
603 ret
= _kadm5_acl_check_permission (kadm_handle
, KADM5_PRIV_GET
,
608 mask
= flags_4_to_5(flags
);
610 ret
= kadm5_get_principal(kadm_handle
, ent
.principal
, &out
, mask
);
611 kadm5_free_principal_ent(kadm_handle
, &ent
);
616 ent_to_values(context
, &out
, mask
, &values
);
618 kadm5_free_principal_ent(kadm_handle
, &out
);
620 store_vals(reply
, &values
);
623 krb5_warn(context
, ret
, "v4-compat GET");
624 return error_code(ret
);
628 kadm_ser_mod(krb5_context context
,
630 krb5_principal principal
,
631 const char *principal_string
,
632 krb5_storage
*message
,
635 Kadm_vals values1
, values2
;
636 kadm5_principal_ent_rec ent
, out
;
641 ret_vals(message
, &values1
);
642 /* why are the old values sent? is the mask the same in the old and
644 ret_vals(message
, &values2
);
646 ret
= values_to_ent(context
, &values2
, &ent
, &mask
);
650 krb5_unparse_name_fixed(context
, ent
.principal
, name
, sizeof(name
));
651 krb5_warnx(context
, "v4-compat %s: MOD %s",
652 principal_string
, name
);
654 ret
= _kadm5_acl_check_permission (kadm_handle
, KADM5_PRIV_MODIFY
,
659 ret
= kadm5_s_modify_principal(kadm_handle
, &ent
, mask
);
661 kadm5_free_principal_ent(kadm_handle
, &ent
);
662 krb5_warn(context
, ret
, "kadm5_s_modify_principal");
666 ret
= kadm5_get_principal(kadm_handle
, ent
.principal
, &out
, mask
);
668 kadm5_free_principal_ent(kadm_handle
, &ent
);
669 krb5_warn(context
, ret
, "kadm5_s_modify_principal");
673 ent_to_values(context
, &out
, mask
, &values1
);
675 kadm5_free_principal_ent(kadm_handle
, &ent
);
676 kadm5_free_principal_ent(kadm_handle
, &out
);
678 store_vals(reply
, &values1
);
681 krb5_warn(context
, ret
, "v4-compat MOD");
682 return error_code(ret
);
686 kadm_ser_del(krb5_context context
,
688 krb5_principal principal
,
689 const char *principal_string
,
690 krb5_storage
*message
,
694 kadm5_principal_ent_rec ent
;
699 ret_vals(message
, &values
);
701 ret
= values_to_ent(context
, &values
, &ent
, &mask
);
705 krb5_unparse_name_fixed(context
, ent
.principal
, name
, sizeof(name
));
706 krb5_warnx(context
, "v4-compat %s: DEL %s",
707 principal_string
, name
);
709 ret
= _kadm5_acl_check_permission (kadm_handle
, KADM5_PRIV_DELETE
,
714 ret
= kadm5_delete_principal(kadm_handle
, ent
.principal
);
716 kadm5_free_principal_ent(kadm_handle
, &ent
);
723 krb5_warn(context
, ret
, "v4-compat ADD");
724 return error_code(ret
);
728 dispatch(krb5_context context
,
730 krb5_principal principal
,
731 const char *principal_string
,
737 krb5_storage
*sp_in
, *sp_out
;
739 sp_in
= krb5_storage_from_data(&msg
);
740 krb5_ret_int8(sp_in
, &command
);
742 sp_out
= krb5_storage_emem();
743 krb5_storage_write(sp_out
, KADM_VERSTR
, KADM_VERSIZE
);
744 krb5_store_int32(sp_out
, 0);
748 retval
= kadm_ser_cpw(context
, kadm_handle
, principal
,
753 retval
= kadm_ser_add(context
, kadm_handle
, principal
,
758 retval
= kadm_ser_get(context
, kadm_handle
, principal
,
763 retval
= kadm_ser_mod(context
, kadm_handle
, principal
,
768 retval
= kadm_ser_del(context
, kadm_handle
, principal
,
773 krb5_warnx(context
, "v4-compat %s: unknown opcode: %d",
774 principal_string
, command
);
775 retval
= KADM_NO_OPCODE
;
778 krb5_storage_free(sp_in
);
780 krb5_storage_seek(sp_out
, KADM_VERSIZE
, SEEK_SET
);
781 krb5_store_int32(sp_out
, retval
);
783 krb5_storage_to_data(sp_out
, reply
);
784 krb5_storage_free(sp_out
);
789 * Decode a v4 kadmin packet in `message' and create a reply in `reply'
793 decode_packet(krb5_context context
,
795 struct sockaddr_in
*admin_addr
,
796 struct sockaddr_in
*client_addr
,
806 char sname
[] = "changepw", sinst
[] = "kerberos";
807 unsigned long checksum
;
808 des_key_schedule schedule
;
809 char *msg
= message
.data
;
811 krb5_principal client
;
813 krb5_keytab_entry entry
;
815 if(message
.length
< KADM_VERSIZE
+ 4
816 || strncmp(msg
, KADM_VERSTR
, KADM_VERSIZE
) != 0) {
817 make_you_lose_packet (KADM_BAD_VER
, reply
);
822 off
+= _krb5_get_int(msg
+ off
, &rlen
, 4);
823 memset(&authent
, 0, sizeof(authent
));
824 authent
.length
= message
.length
- rlen
- KADM_VERSIZE
- 4;
826 if(rlen
> message
.length
- KADM_VERSIZE
- 4
827 || authent
.length
> MAX_KTXT_LEN
) {
828 krb5_warnx(context
, "received bad rlen (%lu)", (unsigned long)rlen
);
829 make_you_lose_packet (KADM_LENGTH_ERROR
, reply
);
833 memcpy(authent
.dat
, (char*)msg
+ off
, authent
.length
);
834 off
+= authent
.length
;
837 krb5_principal principal
;
840 ret
= krb5_make_principal(context
, &principal
, NULL
,
841 "changepw", "kerberos", NULL
);
843 krb5_warn (context
, ret
, "krb5_make_principal");
844 make_you_lose_packet (KADM_NOMEM
, reply
);
847 ret
= krb5_kt_get_entry (context
, keytab
, principal
, 0,
848 ETYPE_DES_CBC_MD5
, &entry
);
849 krb5_kt_close (context
, keytab
);
851 krb5_free_principal(context
, principal
);
852 make_you_lose_packet (KADM_NO_AUTH
, reply
);
855 ret
= krb5_copy_keyblock (context
, &entry
.keyblock
,& key
);
856 krb5_kt_free_entry(context
, &entry
);
857 krb5_free_principal(context
, principal
);
859 if(ret
== KRB5_KT_NOTFOUND
)
860 make_you_lose_packet(KADM_NO_AUTH
, reply
);
863 make_you_lose_packet(KADM_NO_AUTH
, reply
);
864 krb5_warn(context
, ret
, "krb5_kt_read_service_key");
868 if(key
->keyvalue
.length
!= 8)
869 krb5_abortx(context
, "key has wrong length (%lu)",
870 (unsigned long)key
->keyvalue
.length
);
871 krb_set_key(key
->keyvalue
.data
, 0);
872 krb5_free_keyblock(context
, key
);
875 ret
= krb_rd_req(&authent
, sname
, sinst
,
876 client_addr
->sin_addr
.s_addr
, &ad
, NULL
);
879 make_you_lose_packet(ERROR_TABLE_BASE_krb
+ ret
, reply
);
880 krb5_warnx(context
, "krb_rd_req: %d", ret
);
884 ret
= krb5_425_conv_principal(context
, ad
.pname
, ad
.pinst
, ad
.prealm
,
887 krb5_warnx (context
, "krb5_425_conv_principal: %d", ret
);
888 make_you_lose_packet (KADM_NOMEM
, reply
);
892 krb5_unparse_name(context
, client
, &client_str
);
894 ret
= kadm5_init_with_password_ctx(context
,
901 krb5_warn (context
, ret
, "kadm5_init_with_password_ctx");
902 make_you_lose_packet (KADM_NOMEM
, reply
);
906 checksum
= des_quad_cksum((void *)(msg
+ off
), NULL
, rlen
, 0, &ad
.session
);
907 if(checksum
!= ad
.checksum
) {
908 krb5_warnx(context
, "decode_packet: bad checksum");
909 make_you_lose_packet (KADM_BAD_CHK
, reply
);
912 des_set_key(&ad
.session
, schedule
);
913 ret
= krb_rd_priv(msg
+ off
, rlen
, schedule
, &ad
.session
,
914 client_addr
, admin_addr
, &msg_dat
);
916 make_you_lose_packet (ERROR_TABLE_BASE_krb
+ ret
, reply
);
917 krb5_warnx(context
, "krb_rd_priv: %d", ret
);
925 d
.data
= msg_dat
.app_data
;
926 d
.length
= msg_dat
.app_length
;
928 retval
= dispatch(context
, kadm_handle
,
929 client
, client_str
, d
, &r
);
930 krb5_data_alloc(reply
, r
.length
+ 26);
931 reply
->length
= krb_mk_priv(r
.data
, reply
->data
, r
.length
,
932 schedule
, &ad
.session
,
933 admin_addr
, client_addr
);
934 if((ssize_t
)reply
->length
< 0) {
935 make_you_lose_packet(KADM_NO_ENCRYPT
, reply
);
940 krb5_free_principal(context
, client
);
945 handle_v4(krb5_context context
,
951 struct sockaddr_in admin_addr
, client_addr
;
953 krb5_data message
, reply
;
956 addr_len
= sizeof(client_addr
);
957 if (getsockname(fd
, (struct sockaddr
*)&admin_addr
, &addr_len
) < 0)
958 krb5_errx (context
, 1, "getsockname");
959 addr_len
= sizeof(client_addr
);
960 if (getpeername(fd
, (struct sockaddr
*)&client_addr
, &addr_len
) < 0)
961 krb5_errx (context
, 1, "getpeername");
964 doing_useful_work
= 0;
969 krb5_errx(context
, 1, "received too short len (%d < 2)", len
);
970 /* first time around, we have already read len, and two
971 bytes of the version string */
972 krb5_data_alloc(&message
, len
);
973 memcpy(message
.data
, "KA", 2);
974 n
= krb5_net_read(context
, &fd
, (char*)message
.data
+ 2,
979 krb5_err (context
, 1, errno
, "krb5_net_read");
986 n
= krb5_net_read(context
, &fd
, buf
, sizeof(2));
990 krb5_err (context
, 1, errno
, "krb5_net_read");
991 _krb5_get_int(buf
, &tmp
, 2);
992 krb5_data_alloc(&message
, tmp
);
993 n
= krb5_net_read(context
, &fd
, message
.data
, message
.length
);
995 krb5_errx (context
, 1, "EOF in krb5_net_read");
997 krb5_err (context
, 1, errno
, "krb5_net_read");
999 doing_useful_work
= 1;
1000 decode_packet(context
, keytab
, &admin_addr
, &client_addr
,
1002 krb5_data_free(&message
);
1006 _krb5_put_int(buf
, reply
.length
, sizeof(buf
));
1007 n
= krb5_net_write(context
, &fd
, buf
, sizeof(buf
));
1009 krb5_err (context
, 1, errno
, "krb5_net_write");
1010 n
= krb5_net_write(context
, &fd
, reply
.data
, reply
.length
);
1012 krb5_err (context
, 1, errno
, "krb5_net_write");
1013 krb5_data_free(&reply
);