xref: /freebsd/crypto/krb5/src/lib/krb5/krb/ser_auth.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/ser_auth.c - Serialize krb5_authenticator structure */
3 /*
4  * Copyright 1995, 2008 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 #ifndef LEAN_CLIENT
28 
29 #include "k5-int.h"
30 #include "int-proto.h"
31 
32 krb5_error_code
k5_size_authenticator(krb5_authenticator * authenticator,size_t * sizep)33 k5_size_authenticator(krb5_authenticator *authenticator, size_t *sizep)
34 {
35     krb5_error_code     kret;
36     size_t              required;
37 
38     /*
39      * krb5_authenticator requires at minimum:
40      *  krb5_int32              for KV5M_AUTHENTICATOR
41      *  krb5_int32              for seconds
42      *  krb5_int32              for cusec
43      *  krb5_int32              for seq_number
44      *  krb5_int32              for number in authorization_data array.
45      *  krb5_int32              for KV5M_AUTHENTICATOR
46      */
47     kret = EINVAL;
48     if (authenticator != NULL) {
49         required = sizeof(krb5_int32)*6;
50 
51         /* Calculate size required by client, if appropriate */
52         if (authenticator->client)
53             kret = k5_size_principal(authenticator->client, &required);
54         else
55             kret = 0;
56 
57         /* Calculate size required by checksum, if appropriate */
58         if (!kret && authenticator->checksum)
59             kret = k5_size_checksum(authenticator->checksum, &required);
60 
61         /* Calculate size required by subkey, if appropriate */
62         if (!kret && authenticator->subkey)
63             kret = k5_size_keyblock(authenticator->subkey, &required);
64 
65         /* Calculate size required by authorization_data, if appropriate */
66         if (!kret && authenticator->authorization_data) {
67             int i;
68 
69             for (i=0; !kret && authenticator->authorization_data[i]; i++) {
70                 kret = k5_size_authdata(authenticator->authorization_data[i],
71                                         &required);
72             }
73         }
74     }
75     if (!kret)
76         *sizep += required;
77     return(kret);
78 }
79 
80 krb5_error_code
k5_externalize_authenticator(krb5_authenticator * authenticator,krb5_octet ** buffer,size_t * lenremain)81 k5_externalize_authenticator(krb5_authenticator *authenticator,
82                              krb5_octet **buffer, size_t *lenremain)
83 {
84     krb5_error_code     kret;
85     size_t              required;
86     krb5_octet          *bp;
87     size_t              remain;
88     int                 i;
89 
90     required = 0;
91     bp = *buffer;
92     remain = *lenremain;
93     kret = EINVAL;
94     if (authenticator != NULL) {
95         kret = ENOMEM;
96         if (!k5_size_authenticator(authenticator, &required) &&
97             required <= remain) {
98             /* First write our magic number */
99             (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
100 
101             /* Now ctime */
102             (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime,
103                                        &bp, &remain);
104 
105             /* Now cusec */
106             (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec,
107                                        &bp, &remain);
108 
109             /* Now seq_number */
110             (void) krb5_ser_pack_int32(authenticator->seq_number,
111                                        &bp, &remain);
112 
113             /* Now handle client, if appropriate */
114             if (authenticator->client)
115                 kret = k5_externalize_principal(authenticator->client,
116                                                 &bp, &remain);
117             else
118                 kret = 0;
119 
120             /* Now handle checksum, if appropriate */
121             if (!kret && authenticator->checksum)
122                 kret = k5_externalize_checksum(authenticator->checksum,
123                                                &bp, &remain);
124 
125             /* Now handle subkey, if appropriate */
126             if (!kret && authenticator->subkey)
127                 kret = k5_externalize_keyblock(authenticator->subkey,
128                                                &bp, &remain);
129 
130             /* Now handle authorization_data, if appropriate */
131             if (!kret) {
132                 if (authenticator->authorization_data)
133                     for (i=0; authenticator->authorization_data[i]; i++);
134                 else
135                     i = 0;
136                 (void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain);
137 
138                 /* Now pound out the authorization_data */
139                 if (authenticator->authorization_data) {
140                     for (i=0; !kret && authenticator->authorization_data[i];
141                          i++)
142                         kret = k5_externalize_authdata(authenticator->
143                                                        authorization_data[i],
144                                                        &bp, &remain);
145                 }
146             }
147 
148             /*
149              * If we were successful, write trailer then update the pointer and
150              * remaining length;
151              */
152             if (!kret) {
153                 /* Write our trailer */
154                 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
155                 *buffer = bp;
156                 *lenremain = remain;
157             }
158         }
159     }
160     return(kret);
161 }
162 
163 krb5_error_code
k5_internalize_authenticator(krb5_authenticator ** argp,krb5_octet ** buffer,size_t * lenremain)164 k5_internalize_authenticator(krb5_authenticator **argp,
165                              krb5_octet **buffer, size_t *lenremain)
166 {
167     krb5_error_code     kret;
168     krb5_authenticator  *authenticator;
169     krb5_int32          ibuf;
170     krb5_octet          *bp;
171     size_t              remain;
172     int                 i;
173     krb5_int32          nadata;
174     size_t              len;
175 
176     bp = *buffer;
177     remain = *lenremain;
178     kret = EINVAL;
179     /* Read our magic number */
180     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
181         ibuf = 0;
182     if (ibuf == KV5M_AUTHENTICATOR) {
183         kret = ENOMEM;
184 
185         /* Get memory for the authenticator */
186         if ((remain >= (3*sizeof(krb5_int32))) &&
187             (authenticator = (krb5_authenticator *)
188              calloc(1, sizeof(krb5_authenticator)))) {
189 
190             /* Get ctime */
191             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
192             authenticator->ctime = (krb5_timestamp) ibuf;
193 
194             /* Get cusec */
195             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
196             authenticator->cusec = ibuf;
197 
198             /* Get seq_number */
199             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
200             authenticator->seq_number = ibuf;
201 
202             kret = 0;
203 
204             /* Attempt to read in the client */
205             kret = k5_internalize_principal(&authenticator->client,
206                                             &bp, &remain);
207             if (kret == EINVAL)
208                 kret = 0;
209 
210             /* Attempt to read in the checksum */
211             if (!kret) {
212                 kret = k5_internalize_checksum(&authenticator->checksum,
213                                                &bp, &remain);
214                 if (kret == EINVAL)
215                     kret = 0;
216             }
217 
218             /* Attempt to read in the subkey */
219             if (!kret) {
220                 kret = k5_internalize_keyblock(&authenticator->subkey,
221                                                &bp, &remain);
222                 if (kret == EINVAL)
223                     kret = 0;
224             }
225 
226             /* Attempt to read in the authorization data count */
227             if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) {
228                 nadata = ibuf;
229                 len = (size_t) (nadata + 1);
230 
231                 /* Get memory for the authorization data pointers */
232                 if ((authenticator->authorization_data = (krb5_authdata **)
233                      calloc(len, sizeof(krb5_authdata *)))) {
234                     for (i=0; !kret && (i<nadata); i++) {
235                         kret = k5_internalize_authdata(&authenticator->
236                                                        authorization_data[i],
237                                                        &bp, &remain);
238                     }
239 
240                     /* Finally, find the trailer */
241                     if (!kret) {
242                         kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
243                         if (!kret && (ibuf == KV5M_AUTHENTICATOR))
244                             authenticator->magic = KV5M_AUTHENTICATOR;
245                         else
246                             kret = EINVAL;
247                     }
248                 }
249             }
250             if (!kret) {
251                 *buffer = bp;
252                 *lenremain = remain;
253                 *argp = authenticator;
254             }
255             else
256                 krb5_free_authenticator(NULL, authenticator);
257         }
258     }
259     return(kret);
260 }
261 
262 #endif
263