xref: /freebsd/crypto/krb5/src/lib/krb5/krb/ser_actx.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* lib/krb5/krb/ser_actx.c - Serialize krb5_auth_context structure */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright 1995, 2008 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert 
27*7f2fe78bSCy Schubert #include "k5-int.h"
28*7f2fe78bSCy Schubert #include "int-proto.h"
29*7f2fe78bSCy Schubert #include "auth_con.h"
30*7f2fe78bSCy Schubert 
31*7f2fe78bSCy Schubert #define TOKEN_RADDR     950916
32*7f2fe78bSCy Schubert #define TOKEN_RPORT     950917
33*7f2fe78bSCy Schubert #define TOKEN_LADDR     950918
34*7f2fe78bSCy Schubert #define TOKEN_LPORT     950919
35*7f2fe78bSCy Schubert #define TOKEN_KEYBLOCK  950920
36*7f2fe78bSCy Schubert #define TOKEN_LSKBLOCK  950921
37*7f2fe78bSCy Schubert #define TOKEN_RSKBLOCK  950922
38*7f2fe78bSCy Schubert 
39*7f2fe78bSCy Schubert krb5_error_code
k5_size_auth_context(krb5_auth_context auth_context,size_t * sizep)40*7f2fe78bSCy Schubert k5_size_auth_context(krb5_auth_context auth_context, size_t *sizep)
41*7f2fe78bSCy Schubert {
42*7f2fe78bSCy Schubert     krb5_error_code     kret;
43*7f2fe78bSCy Schubert     size_t              required;
44*7f2fe78bSCy Schubert 
45*7f2fe78bSCy Schubert     /*
46*7f2fe78bSCy Schubert      * krb5_auth_context requires at minimum:
47*7f2fe78bSCy Schubert      *  krb5_int32              for KV5M_AUTH_CONTEXT
48*7f2fe78bSCy Schubert      *  krb5_int32              for auth_context_flags
49*7f2fe78bSCy Schubert      *  krb5_int32              for remote_seq_number
50*7f2fe78bSCy Schubert      *  krb5_int32              for local_seq_number
51*7f2fe78bSCy Schubert      *  krb5_int32              for req_cksumtype
52*7f2fe78bSCy Schubert      *  krb5_int32              for safe_cksumtype
53*7f2fe78bSCy Schubert      *  krb5_int32              for size of i_vector
54*7f2fe78bSCy Schubert      *  krb5_int32              for KV5M_AUTH_CONTEXT
55*7f2fe78bSCy Schubert      */
56*7f2fe78bSCy Schubert     kret = EINVAL;
57*7f2fe78bSCy Schubert     if (auth_context != NULL) {
58*7f2fe78bSCy Schubert         kret = 0;
59*7f2fe78bSCy Schubert 
60*7f2fe78bSCy Schubert         required = auth_context->cstate.length;
61*7f2fe78bSCy Schubert         required += sizeof(krb5_int32)*8;
62*7f2fe78bSCy Schubert 
63*7f2fe78bSCy Schubert         /* Calculate size required by remote_addr, if appropriate */
64*7f2fe78bSCy Schubert         if (!kret && auth_context->remote_addr) {
65*7f2fe78bSCy Schubert             kret = k5_size_address(auth_context->remote_addr, &required);
66*7f2fe78bSCy Schubert             if (!kret)
67*7f2fe78bSCy Schubert                 required += sizeof(krb5_int32);
68*7f2fe78bSCy Schubert         }
69*7f2fe78bSCy Schubert 
70*7f2fe78bSCy Schubert         /* Calculate size required by remote_port, if appropriate */
71*7f2fe78bSCy Schubert         if (!kret && auth_context->remote_port) {
72*7f2fe78bSCy Schubert             kret = k5_size_address(auth_context->remote_port, &required);
73*7f2fe78bSCy Schubert             if (!kret)
74*7f2fe78bSCy Schubert                 required += sizeof(krb5_int32);
75*7f2fe78bSCy Schubert         }
76*7f2fe78bSCy Schubert 
77*7f2fe78bSCy Schubert         /* Calculate size required by local_addr, if appropriate */
78*7f2fe78bSCy Schubert         if (!kret && auth_context->local_addr) {
79*7f2fe78bSCy Schubert             kret = k5_size_address(auth_context->local_addr, &required);
80*7f2fe78bSCy Schubert             if (!kret)
81*7f2fe78bSCy Schubert                 required += sizeof(krb5_int32);
82*7f2fe78bSCy Schubert         }
83*7f2fe78bSCy Schubert 
84*7f2fe78bSCy Schubert         /* Calculate size required by local_port, if appropriate */
85*7f2fe78bSCy Schubert         if (!kret && auth_context->local_port) {
86*7f2fe78bSCy Schubert             kret = k5_size_address(auth_context->local_port, &required);
87*7f2fe78bSCy Schubert             if (!kret)
88*7f2fe78bSCy Schubert                 required += sizeof(krb5_int32);
89*7f2fe78bSCy Schubert         }
90*7f2fe78bSCy Schubert 
91*7f2fe78bSCy Schubert         /* Calculate size required by key, if appropriate */
92*7f2fe78bSCy Schubert         if (!kret && auth_context->key) {
93*7f2fe78bSCy Schubert             kret = k5_size_keyblock(&auth_context->key->keyblock, &required);
94*7f2fe78bSCy Schubert             if (!kret)
95*7f2fe78bSCy Schubert                 required += sizeof(krb5_int32);
96*7f2fe78bSCy Schubert         }
97*7f2fe78bSCy Schubert 
98*7f2fe78bSCy Schubert         /* Calculate size required by send_subkey, if appropriate */
99*7f2fe78bSCy Schubert         if (!kret && auth_context->send_subkey) {
100*7f2fe78bSCy Schubert             kret = k5_size_keyblock(&auth_context->send_subkey->keyblock,
101*7f2fe78bSCy Schubert                                     &required);
102*7f2fe78bSCy Schubert             if (!kret)
103*7f2fe78bSCy Schubert                 required += sizeof(krb5_int32);
104*7f2fe78bSCy Schubert         }
105*7f2fe78bSCy Schubert 
106*7f2fe78bSCy Schubert         /* Calculate size required by recv_subkey, if appropriate */
107*7f2fe78bSCy Schubert         if (!kret && auth_context->recv_subkey) {
108*7f2fe78bSCy Schubert             kret = k5_size_keyblock(&auth_context->recv_subkey->keyblock,
109*7f2fe78bSCy Schubert                                     &required);
110*7f2fe78bSCy Schubert             if (!kret)
111*7f2fe78bSCy Schubert                 required += sizeof(krb5_int32);
112*7f2fe78bSCy Schubert         }
113*7f2fe78bSCy Schubert 
114*7f2fe78bSCy Schubert         /* Calculate size required by authentp, if appropriate */
115*7f2fe78bSCy Schubert         if (!kret && auth_context->authentp)
116*7f2fe78bSCy Schubert             kret = k5_size_authenticator(auth_context->authentp, &required);
117*7f2fe78bSCy Schubert 
118*7f2fe78bSCy Schubert     }
119*7f2fe78bSCy Schubert     if (!kret)
120*7f2fe78bSCy Schubert         *sizep += required;
121*7f2fe78bSCy Schubert     return(kret);
122*7f2fe78bSCy Schubert }
123*7f2fe78bSCy Schubert 
124*7f2fe78bSCy Schubert krb5_error_code
k5_externalize_auth_context(krb5_auth_context auth_context,krb5_octet ** buffer,size_t * lenremain)125*7f2fe78bSCy Schubert k5_externalize_auth_context(krb5_auth_context auth_context,
126*7f2fe78bSCy Schubert                             krb5_octet **buffer, size_t *lenremain)
127*7f2fe78bSCy Schubert {
128*7f2fe78bSCy Schubert     krb5_error_code     kret;
129*7f2fe78bSCy Schubert     size_t              required;
130*7f2fe78bSCy Schubert     krb5_octet          *bp;
131*7f2fe78bSCy Schubert     size_t              remain;
132*7f2fe78bSCy Schubert 
133*7f2fe78bSCy Schubert     required = 0;
134*7f2fe78bSCy Schubert     bp = *buffer;
135*7f2fe78bSCy Schubert     remain = *lenremain;
136*7f2fe78bSCy Schubert     kret = EINVAL;
137*7f2fe78bSCy Schubert     if (auth_context != NULL) {
138*7f2fe78bSCy Schubert         kret = ENOMEM;
139*7f2fe78bSCy Schubert         if (!k5_size_auth_context(auth_context, &required) &&
140*7f2fe78bSCy Schubert             required <= remain) {
141*7f2fe78bSCy Schubert 
142*7f2fe78bSCy Schubert             /* Write fixed portion */
143*7f2fe78bSCy Schubert             (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain);
144*7f2fe78bSCy Schubert             (void) krb5_ser_pack_int32(auth_context->auth_context_flags,
145*7f2fe78bSCy Schubert                                        &bp, &remain);
146*7f2fe78bSCy Schubert             (void) krb5_ser_pack_int32(auth_context->remote_seq_number,
147*7f2fe78bSCy Schubert                                        &bp, &remain);
148*7f2fe78bSCy Schubert             (void) krb5_ser_pack_int32(auth_context->local_seq_number,
149*7f2fe78bSCy Schubert                                        &bp, &remain);
150*7f2fe78bSCy Schubert             (void) krb5_ser_pack_int32((krb5_int32) auth_context->req_cksumtype,
151*7f2fe78bSCy Schubert                                        &bp, &remain);
152*7f2fe78bSCy Schubert             (void) krb5_ser_pack_int32((krb5_int32) auth_context->safe_cksumtype,
153*7f2fe78bSCy Schubert                                        &bp, &remain);
154*7f2fe78bSCy Schubert 
155*7f2fe78bSCy Schubert             /* Write the cipher state */
156*7f2fe78bSCy Schubert             (void) krb5_ser_pack_int32(auth_context->cstate.length, &bp,
157*7f2fe78bSCy Schubert                                        &remain);
158*7f2fe78bSCy Schubert             (void) krb5_ser_pack_bytes((krb5_octet *)auth_context->cstate.data,
159*7f2fe78bSCy Schubert                                        auth_context->cstate.length,
160*7f2fe78bSCy Schubert                                        &bp, &remain);
161*7f2fe78bSCy Schubert 
162*7f2fe78bSCy Schubert             kret = 0;
163*7f2fe78bSCy Schubert 
164*7f2fe78bSCy Schubert             /* Now handle remote_addr, if appropriate */
165*7f2fe78bSCy Schubert             if (!kret && auth_context->remote_addr) {
166*7f2fe78bSCy Schubert                 (void) krb5_ser_pack_int32(TOKEN_RADDR, &bp, &remain);
167*7f2fe78bSCy Schubert                 kret = k5_externalize_address(auth_context->remote_addr,
168*7f2fe78bSCy Schubert                                               &bp, &remain);
169*7f2fe78bSCy Schubert             }
170*7f2fe78bSCy Schubert 
171*7f2fe78bSCy Schubert             /* Now handle remote_port, if appropriate */
172*7f2fe78bSCy Schubert             if (!kret && auth_context->remote_port) {
173*7f2fe78bSCy Schubert                 (void) krb5_ser_pack_int32(TOKEN_RPORT, &bp, &remain);
174*7f2fe78bSCy Schubert                 kret = k5_externalize_address(auth_context->remote_addr,
175*7f2fe78bSCy Schubert                                               &bp, &remain);
176*7f2fe78bSCy Schubert             }
177*7f2fe78bSCy Schubert 
178*7f2fe78bSCy Schubert             /* Now handle local_addr, if appropriate */
179*7f2fe78bSCy Schubert             if (!kret && auth_context->local_addr) {
180*7f2fe78bSCy Schubert                 (void) krb5_ser_pack_int32(TOKEN_LADDR, &bp, &remain);
181*7f2fe78bSCy Schubert                 kret = k5_externalize_address(auth_context->local_addr,
182*7f2fe78bSCy Schubert                                               &bp, &remain);
183*7f2fe78bSCy Schubert             }
184*7f2fe78bSCy Schubert 
185*7f2fe78bSCy Schubert             /* Now handle local_port, if appropriate */
186*7f2fe78bSCy Schubert             if (!kret && auth_context->local_port) {
187*7f2fe78bSCy Schubert                 (void) krb5_ser_pack_int32(TOKEN_LPORT, &bp, &remain);
188*7f2fe78bSCy Schubert                 kret = k5_externalize_address(auth_context->local_addr,
189*7f2fe78bSCy Schubert                                               &bp, &remain);
190*7f2fe78bSCy Schubert             }
191*7f2fe78bSCy Schubert 
192*7f2fe78bSCy Schubert             /* Now handle keyblock, if appropriate */
193*7f2fe78bSCy Schubert             if (!kret && auth_context->key) {
194*7f2fe78bSCy Schubert                 (void) krb5_ser_pack_int32(TOKEN_KEYBLOCK, &bp, &remain);
195*7f2fe78bSCy Schubert                 kret = k5_externalize_keyblock(&auth_context->key->keyblock,
196*7f2fe78bSCy Schubert                                                &bp, &remain);
197*7f2fe78bSCy Schubert             }
198*7f2fe78bSCy Schubert 
199*7f2fe78bSCy Schubert             /* Now handle subkey, if appropriate */
200*7f2fe78bSCy Schubert             if (!kret && auth_context->send_subkey) {
201*7f2fe78bSCy Schubert                 (void) krb5_ser_pack_int32(TOKEN_LSKBLOCK, &bp, &remain);
202*7f2fe78bSCy Schubert                 kret = k5_externalize_keyblock(&auth_context->
203*7f2fe78bSCy Schubert                                                send_subkey->keyblock,
204*7f2fe78bSCy Schubert                                                &bp, &remain);
205*7f2fe78bSCy Schubert             }
206*7f2fe78bSCy Schubert 
207*7f2fe78bSCy Schubert             /* Now handle subkey, if appropriate */
208*7f2fe78bSCy Schubert             if (!kret && auth_context->recv_subkey) {
209*7f2fe78bSCy Schubert                 (void) krb5_ser_pack_int32(TOKEN_RSKBLOCK, &bp, &remain);
210*7f2fe78bSCy Schubert                 kret = k5_externalize_keyblock(&auth_context->
211*7f2fe78bSCy Schubert                                                recv_subkey->keyblock,
212*7f2fe78bSCy Schubert                                                &bp, &remain);
213*7f2fe78bSCy Schubert             }
214*7f2fe78bSCy Schubert 
215*7f2fe78bSCy Schubert             /* Now handle authentp, if appropriate */
216*7f2fe78bSCy Schubert             if (!kret && auth_context->authentp)
217*7f2fe78bSCy Schubert                 kret = k5_externalize_authenticator(auth_context->authentp,
218*7f2fe78bSCy Schubert                                                     &bp, &remain);
219*7f2fe78bSCy Schubert 
220*7f2fe78bSCy Schubert             /*
221*7f2fe78bSCy Schubert              * If we were successful, write trailer then update the pointer and
222*7f2fe78bSCy Schubert              * remaining length;
223*7f2fe78bSCy Schubert              */
224*7f2fe78bSCy Schubert             if (!kret) {
225*7f2fe78bSCy Schubert                 /* Write our trailer */
226*7f2fe78bSCy Schubert                 (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain);
227*7f2fe78bSCy Schubert                 *buffer = bp;
228*7f2fe78bSCy Schubert                 *lenremain = remain;
229*7f2fe78bSCy Schubert             }
230*7f2fe78bSCy Schubert         }
231*7f2fe78bSCy Schubert     }
232*7f2fe78bSCy Schubert     return(kret);
233*7f2fe78bSCy Schubert }
234*7f2fe78bSCy Schubert 
235*7f2fe78bSCy Schubert /* Internalize a keyblock and convert it to a key. */
236*7f2fe78bSCy Schubert static krb5_error_code
intern_key(krb5_key * key,krb5_octet ** bp,size_t * sp)237*7f2fe78bSCy Schubert intern_key(krb5_key *key, krb5_octet **bp, size_t *sp)
238*7f2fe78bSCy Schubert {
239*7f2fe78bSCy Schubert     krb5_keyblock *keyblock;
240*7f2fe78bSCy Schubert     krb5_error_code ret;
241*7f2fe78bSCy Schubert 
242*7f2fe78bSCy Schubert     ret = k5_internalize_keyblock(&keyblock, bp, sp);
243*7f2fe78bSCy Schubert     if (ret != 0)
244*7f2fe78bSCy Schubert         return ret;
245*7f2fe78bSCy Schubert     ret = krb5_k_create_key(NULL, keyblock, key);
246*7f2fe78bSCy Schubert     krb5_free_keyblock(NULL, keyblock);
247*7f2fe78bSCy Schubert     return ret;
248*7f2fe78bSCy Schubert }
249*7f2fe78bSCy Schubert 
250*7f2fe78bSCy Schubert krb5_error_code
k5_internalize_auth_context(krb5_auth_context * argp,krb5_octet ** buffer,size_t * lenremain)251*7f2fe78bSCy Schubert k5_internalize_auth_context(krb5_auth_context *argp,
252*7f2fe78bSCy Schubert                             krb5_octet **buffer, size_t *lenremain)
253*7f2fe78bSCy Schubert {
254*7f2fe78bSCy Schubert     krb5_error_code     kret;
255*7f2fe78bSCy Schubert     krb5_auth_context   auth_context;
256*7f2fe78bSCy Schubert     krb5_int32          ibuf;
257*7f2fe78bSCy Schubert     krb5_octet          *bp;
258*7f2fe78bSCy Schubert     size_t              remain;
259*7f2fe78bSCy Schubert     krb5_int32          cstate_len;
260*7f2fe78bSCy Schubert     krb5_int32          tag;
261*7f2fe78bSCy Schubert 
262*7f2fe78bSCy Schubert     bp = *buffer;
263*7f2fe78bSCy Schubert     remain = *lenremain;
264*7f2fe78bSCy Schubert     kret = EINVAL;
265*7f2fe78bSCy Schubert     /* Read our magic number */
266*7f2fe78bSCy Schubert     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
267*7f2fe78bSCy Schubert         ibuf = 0;
268*7f2fe78bSCy Schubert     if (ibuf == KV5M_AUTH_CONTEXT) {
269*7f2fe78bSCy Schubert         kret = ENOMEM;
270*7f2fe78bSCy Schubert 
271*7f2fe78bSCy Schubert         /* Get memory for the auth_context */
272*7f2fe78bSCy Schubert         if ((remain >= (5*sizeof(krb5_int32))) &&
273*7f2fe78bSCy Schubert             (auth_context = (krb5_auth_context)
274*7f2fe78bSCy Schubert              calloc(1, sizeof(struct _krb5_auth_context)))) {
275*7f2fe78bSCy Schubert 
276*7f2fe78bSCy Schubert             /* Get auth_context_flags */
277*7f2fe78bSCy Schubert             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
278*7f2fe78bSCy Schubert             auth_context->auth_context_flags = ibuf;
279*7f2fe78bSCy Schubert 
280*7f2fe78bSCy Schubert             /* Get remote_seq_number */
281*7f2fe78bSCy Schubert             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
282*7f2fe78bSCy Schubert             auth_context->remote_seq_number = ibuf;
283*7f2fe78bSCy Schubert 
284*7f2fe78bSCy Schubert             /* Get local_seq_number */
285*7f2fe78bSCy Schubert             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
286*7f2fe78bSCy Schubert             auth_context->local_seq_number = ibuf;
287*7f2fe78bSCy Schubert 
288*7f2fe78bSCy Schubert             /* Get req_cksumtype */
289*7f2fe78bSCy Schubert             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
290*7f2fe78bSCy Schubert             auth_context->req_cksumtype = (krb5_cksumtype) ibuf;
291*7f2fe78bSCy Schubert 
292*7f2fe78bSCy Schubert             /* Get safe_cksumtype */
293*7f2fe78bSCy Schubert             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
294*7f2fe78bSCy Schubert             auth_context->safe_cksumtype = (krb5_cksumtype) ibuf;
295*7f2fe78bSCy Schubert 
296*7f2fe78bSCy Schubert             /* Get length of cstate */
297*7f2fe78bSCy Schubert             (void) krb5_ser_unpack_int32(&cstate_len, &bp, &remain);
298*7f2fe78bSCy Schubert 
299*7f2fe78bSCy Schubert             if (cstate_len) {
300*7f2fe78bSCy Schubert                 kret = alloc_data(&auth_context->cstate, cstate_len);
301*7f2fe78bSCy Schubert                 if (!kret) {
302*7f2fe78bSCy Schubert                     kret = krb5_ser_unpack_bytes((krb5_octet *)
303*7f2fe78bSCy Schubert                                                  auth_context->cstate.data,
304*7f2fe78bSCy Schubert                                                  cstate_len, &bp, &remain);
305*7f2fe78bSCy Schubert                 }
306*7f2fe78bSCy Schubert             }
307*7f2fe78bSCy Schubert             else
308*7f2fe78bSCy Schubert                 kret = 0;
309*7f2fe78bSCy Schubert 
310*7f2fe78bSCy Schubert             /* Peek at next token */
311*7f2fe78bSCy Schubert             tag = 0;
312*7f2fe78bSCy Schubert             if (!kret)
313*7f2fe78bSCy Schubert                 kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
314*7f2fe78bSCy Schubert 
315*7f2fe78bSCy Schubert             /* This is the remote_addr */
316*7f2fe78bSCy Schubert             if (!kret && (tag == TOKEN_RADDR)) {
317*7f2fe78bSCy Schubert                 if (!(kret = k5_internalize_address(&auth_context->remote_addr,
318*7f2fe78bSCy Schubert                                                     &bp, &remain)))
319*7f2fe78bSCy Schubert                     kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
320*7f2fe78bSCy Schubert             }
321*7f2fe78bSCy Schubert 
322*7f2fe78bSCy Schubert             /* This is the remote_port */
323*7f2fe78bSCy Schubert             if (!kret && (tag == TOKEN_RPORT)) {
324*7f2fe78bSCy Schubert                 if (!(kret = k5_internalize_address(&auth_context->remote_port,
325*7f2fe78bSCy Schubert                                                     &bp, &remain)))
326*7f2fe78bSCy Schubert                     kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
327*7f2fe78bSCy Schubert             }
328*7f2fe78bSCy Schubert 
329*7f2fe78bSCy Schubert             /* This is the local_addr */
330*7f2fe78bSCy Schubert             if (!kret && (tag == TOKEN_LADDR)) {
331*7f2fe78bSCy Schubert                 if (!(kret = k5_internalize_address(&auth_context->local_addr,
332*7f2fe78bSCy Schubert                                                     &bp, &remain)))
333*7f2fe78bSCy Schubert                     kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
334*7f2fe78bSCy Schubert             }
335*7f2fe78bSCy Schubert 
336*7f2fe78bSCy Schubert             /* This is the local_port */
337*7f2fe78bSCy Schubert             if (!kret && (tag == TOKEN_LPORT)) {
338*7f2fe78bSCy Schubert                 if (!(kret = k5_internalize_address(&auth_context->local_port,
339*7f2fe78bSCy Schubert                                                     &bp, &remain)))
340*7f2fe78bSCy Schubert                     kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
341*7f2fe78bSCy Schubert             }
342*7f2fe78bSCy Schubert 
343*7f2fe78bSCy Schubert             /* This is the keyblock */
344*7f2fe78bSCy Schubert             if (!kret && (tag == TOKEN_KEYBLOCK)) {
345*7f2fe78bSCy Schubert                 if (!(kret = intern_key(&auth_context->key, &bp, &remain)))
346*7f2fe78bSCy Schubert                     kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
347*7f2fe78bSCy Schubert             }
348*7f2fe78bSCy Schubert 
349*7f2fe78bSCy Schubert             /* This is the send_subkey */
350*7f2fe78bSCy Schubert             if (!kret && (tag == TOKEN_LSKBLOCK)) {
351*7f2fe78bSCy Schubert                 if (!(kret = intern_key(&auth_context->send_subkey,
352*7f2fe78bSCy Schubert                                         &bp, &remain)))
353*7f2fe78bSCy Schubert                     kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
354*7f2fe78bSCy Schubert             }
355*7f2fe78bSCy Schubert 
356*7f2fe78bSCy Schubert             /* This is the recv_subkey */
357*7f2fe78bSCy Schubert             if (!kret) {
358*7f2fe78bSCy Schubert                 if (tag == TOKEN_RSKBLOCK) {
359*7f2fe78bSCy Schubert                     kret = intern_key(&auth_context->recv_subkey,
360*7f2fe78bSCy Schubert                                       &bp, &remain);
361*7f2fe78bSCy Schubert                 }
362*7f2fe78bSCy Schubert                 else {
363*7f2fe78bSCy Schubert                     /*
364*7f2fe78bSCy Schubert                      * We read the next tag, but it's not of any use here, so
365*7f2fe78bSCy Schubert                      * we effectively 'unget' it here.
366*7f2fe78bSCy Schubert                      */
367*7f2fe78bSCy Schubert                     bp -= sizeof(krb5_int32);
368*7f2fe78bSCy Schubert                     remain += sizeof(krb5_int32);
369*7f2fe78bSCy Schubert                 }
370*7f2fe78bSCy Schubert             }
371*7f2fe78bSCy Schubert 
372*7f2fe78bSCy Schubert             /* Now find the authentp */
373*7f2fe78bSCy Schubert             if (!kret) {
374*7f2fe78bSCy Schubert                 kret = k5_internalize_authenticator(&auth_context->authentp,
375*7f2fe78bSCy Schubert                                                     &bp, &remain);
376*7f2fe78bSCy Schubert                 if (kret == EINVAL)
377*7f2fe78bSCy Schubert                     kret = 0;
378*7f2fe78bSCy Schubert             }
379*7f2fe78bSCy Schubert 
380*7f2fe78bSCy Schubert             /* Finally, find the trailer */
381*7f2fe78bSCy Schubert             if (!kret) {
382*7f2fe78bSCy Schubert                 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
383*7f2fe78bSCy Schubert                 if (!kret && (ibuf != KV5M_AUTH_CONTEXT))
384*7f2fe78bSCy Schubert                     kret = EINVAL;
385*7f2fe78bSCy Schubert             }
386*7f2fe78bSCy Schubert             if (!kret) {
387*7f2fe78bSCy Schubert                 *buffer = bp;
388*7f2fe78bSCy Schubert                 *lenremain = remain;
389*7f2fe78bSCy Schubert                 auth_context->magic = KV5M_AUTH_CONTEXT;
390*7f2fe78bSCy Schubert                 *argp = auth_context;
391*7f2fe78bSCy Schubert             }
392*7f2fe78bSCy Schubert             else
393*7f2fe78bSCy Schubert                 krb5_auth_con_free(NULL, auth_context);
394*7f2fe78bSCy Schubert         }
395*7f2fe78bSCy Schubert     }
396*7f2fe78bSCy Schubert     return(kret);
397*7f2fe78bSCy Schubert }
398