1/*
2 * lib/krb5/krb/ser_cksum.c
3 *
4 * Copyright 1995 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
28/*
29 * ser_cksum.c - Serialize a krb5_checksum structure.
30 */
31#include "k5-int.h"
32#include "int-proto.h"
33
34/*
35 * Routines to deal with externalizing the krb5_checksum:
36 *	krb5_checksum_esize();
37 *	krb5_checksum_externalize();
38 *	krb5_checksum_internalize();
39 */
40static krb5_error_code krb5_checksum_esize
41	(krb5_context, krb5_pointer, size_t *);
42static krb5_error_code krb5_checksum_externalize
43	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
44static krb5_error_code krb5_checksum_internalize
45	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
46
47/* Local data */
48static const krb5_ser_entry krb5_checksum_ser_entry = {
49    KV5M_CHECKSUM,			/* Type			*/
50    krb5_checksum_esize,		/* Sizer routine	*/
51    krb5_checksum_externalize,		/* Externalize routine	*/
52    krb5_checksum_internalize		/* Internalize routine	*/
53};
54
55/*
56 * krb5_checksum_esize()	- Determine the size required to externalize
57 *				  the krb5_checksum.
58 */
59/*ARGSUSED*/
60static krb5_error_code
61krb5_checksum_esize(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
62{
63    krb5_error_code	kret;
64    krb5_checksum	*checksum;
65
66    /*
67     * krb5_checksum requires:
68     *	krb5_int32		for KV5M_CHECKSUM
69     *	krb5_int32		for checksum_type
70     *	krb5_int32		for length
71     *	krb5_int32		for KV5M_CHECKSUM
72     *	checksum->length	for contents
73     */
74    kret = EINVAL;
75    /* Solaris Kerberos */
76    checksum = (krb5_checksum *) arg;
77    if (checksum) {
78	*sizep += (sizeof(krb5_int32) +
79		   sizeof(krb5_int32) +
80		   sizeof(krb5_int32) +
81		   sizeof(krb5_int32) +
82		   (size_t) checksum->length);
83	kret = 0;
84    }
85    return(kret);
86}
87
88/*
89 * krb5_checksum_externalize()	- Externalize the krb5_checksum.
90 */
91static krb5_error_code
92krb5_checksum_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
93{
94    krb5_error_code	kret;
95    krb5_checksum	*checksum;
96    size_t		required;
97    krb5_octet		*bp;
98    size_t		remain;
99
100    required = 0;
101    bp = *buffer;
102    remain = *lenremain;
103    kret = EINVAL;
104    /* Solaris Kerberos */
105    checksum = (krb5_checksum *) arg;
106    if (checksum) {
107	kret = ENOMEM;
108	if (!krb5_checksum_esize(kcontext, arg, &required) &&
109	    (required <= remain)) {
110	    /* Our identifier */
111	    (void) krb5_ser_pack_int32(KV5M_CHECKSUM, &bp, &remain);
112
113	    /* Our checksum_type */
114	    (void) krb5_ser_pack_int32((krb5_int32) checksum->checksum_type,
115				       &bp, &remain);
116
117	    /* Our length */
118	    (void) krb5_ser_pack_int32((krb5_int32) checksum->length,
119				       &bp, &remain);
120
121	    /* Our contents */
122	    (void) krb5_ser_pack_bytes(checksum->contents,
123				       (size_t) checksum->length,
124				       &bp, &remain);
125
126	    /* Finally, our trailer */
127	    (void) krb5_ser_pack_int32(KV5M_CHECKSUM, &bp, &remain);
128
129	    kret = 0;
130	    *buffer = bp;
131	    *lenremain = remain;
132	}
133    }
134    return(kret);
135}
136
137/*
138 * krb5_checksum_internalize()	- Internalize the krb5_checksum.
139 */
140/*ARGSUSED*/
141static krb5_error_code
142krb5_checksum_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
143{
144    krb5_error_code	kret;
145    krb5_checksum	*checksum;
146    krb5_int32		ibuf;
147    krb5_octet		*bp;
148    size_t		remain;
149
150    bp = *buffer;
151    remain = *lenremain;
152    kret = EINVAL;
153    /* Read our magic number */
154    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
155	ibuf = 0;
156    if (ibuf == KV5M_CHECKSUM) {
157	kret = ENOMEM;
158
159	/* Get a checksum */
160	if ((remain >= (2*sizeof(krb5_int32))) &&
161	    (checksum = (krb5_checksum *) MALLOC(sizeof(krb5_checksum)))) {
162	    (void) memset(checksum, 0, sizeof(krb5_checksum));
163
164	    /* Get the checksum_type */
165	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
166	    checksum->checksum_type = (krb5_cksumtype) ibuf;
167
168	    /* Get the length */
169	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
170	    checksum->length = (int) ibuf;
171
172	    /* Get the string */
173	    /* Solaris Kerberos */
174	    if (ibuf)
175		checksum->contents = (krb5_octet *)
176		 			 MALLOC((size_t) (ibuf));
177
178	    if (!ibuf ||
179		((checksum->contents) &&
180		 !(kret = krb5_ser_unpack_bytes(checksum->contents,
181						(size_t) ibuf,
182						&bp, &remain)))) {
183
184		/* Get the trailer */
185		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
186		if (!kret && (ibuf == KV5M_CHECKSUM)) {
187		    checksum->magic = KV5M_CHECKSUM;
188		    *buffer = bp;
189		    *lenremain = remain;
190		    *argp = (krb5_pointer) checksum;
191		}
192		else
193		    kret = EINVAL;
194	    }
195	    if (kret) {
196		if (checksum->contents)
197		    FREE(checksum->contents, checksum->length);
198		FREE(checksum, sizeof (krb5_checksum));
199	    }
200	}
201    }
202    return(kret);
203}
204
205/*
206 * Register the checksum serializer.
207 */
208krb5_error_code
209krb5_ser_checksum_init(krb5_context kcontext)
210{
211    return(krb5_register_serializer(kcontext, &krb5_checksum_ser_entry));
212}
213