1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6
7/*
8 * lib/krb5/krb/ser_princ.c
9 *
10 * Copyright 1995 by the Massachusetts Institute of Technology.
11 * All Rights Reserved.
12 *
13 * Export of this software from the United States of America may
14 *   require a specific license from the United States Government.
15 *   It is the responsibility of any person or organization contemplating
16 *   export to obtain such a license before exporting.
17 *
18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19 * distribute this software and its documentation for any purpose and
20 * without fee is hereby granted, provided that the above copyright
21 * notice appear in all copies and that both that copyright notice and
22 * this permission notice appear in supporting documentation, and that
23 * the name of M.I.T. not be used in advertising or publicity pertaining
24 * to distribution of the software without specific, written prior
25 * permission.  Furthermore if you modify this software you must label
26 * your software as modified software and not distribute it in such a
27 * fashion that it might be confused with the original M.I.T. software.
28 * M.I.T. makes no representations about the suitability of
29 * this software for any purpose.  It is provided "as is" without express
30 * or implied warranty.
31 *
32 */
33
34/*
35 * ser_princ.c - Serialize a krb5_principal structure.
36 */
37#include "k5-int.h"
38#include "int-proto.h"
39
40/*
41 * Routines to deal with externalizing the krb5_principal:
42 *	krb5_principal_size();
43 *	krb5_principal_externalize();
44 *	krb5_principal_internalize();
45 */
46static krb5_error_code krb5_principal_size
47	(krb5_context, krb5_pointer, size_t *);
48static krb5_error_code krb5_principal_externalize
49	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
50static krb5_error_code krb5_principal_internalize
51	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
52
53/* Local data */
54static const krb5_ser_entry krb5_principal_ser_entry = {
55    KV5M_PRINCIPAL,			/* Type			*/
56    krb5_principal_size,		/* Sizer routine	*/
57    krb5_principal_externalize,		/* Externalize routine	*/
58    krb5_principal_internalize		/* Internalize routine	*/
59};
60
61/*
62 * krb5_principal_size()	- Determine the size required to externalize
63 *				  the krb5_principal.
64 */
65static krb5_error_code
66krb5_principal_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
67{
68    krb5_error_code	kret;
69    krb5_principal	principal;
70    char		*fname;
71
72    /*
73     * krb5_principal requires:
74     *	krb5_int32			for KV5M_PRINCIPAL
75     *	krb5_int32			for flattened name size
76     *	strlen(name)			for name.
77     *	krb5_int32			for KV5M_PRINCIPAL
78     */
79    kret = EINVAL;
80    /* Solaris Kerberos */
81    principal = (krb5_principal) arg;
82    if ((principal) &&
83	!(kret = krb5_unparse_name(kcontext, principal, &fname))) {
84	*sizep += (3*sizeof(krb5_int32)) + strlen(fname);
85	/* Solaris Kerberos */
86	krb5_xfree_wrap(fname, strlen(fname) + 1);
87    }
88    return(kret);
89}
90
91/*
92 * krb5_principal_externalize()	- Externalize the krb5_principal.
93 */
94static krb5_error_code
95krb5_principal_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
96{
97    krb5_error_code	kret;
98    krb5_principal	principal;
99    size_t		required;
100    krb5_octet		*bp;
101    size_t		remain;
102    char		*fname;
103
104    required = 0;
105    bp = *buffer;
106    remain = *lenremain;
107    kret = EINVAL;
108    /* Solaris Kerberos */
109    principal = (krb5_principal) arg;
110    if (principal) {
111	kret = ENOMEM;
112	if (!krb5_principal_size(kcontext, arg, &required) &&
113	    (required <= remain)) {
114	    if (!(kret = krb5_unparse_name(kcontext, principal, &fname))) {
115
116		(void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain);
117		(void) krb5_ser_pack_int32((krb5_int32) strlen(fname),
118					   &bp, &remain);
119		(void) krb5_ser_pack_bytes((krb5_octet *) fname,
120					   strlen(fname), &bp, &remain);
121		(void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain);
122		*buffer = bp;
123		*lenremain = remain;
124
125		/* Solaris Kerberos */
126		krb5_xfree_wrap(fname, strlen(fname) + 1);
127	    }
128	}
129    }
130    return(kret);
131}
132
133/*
134 * krb5_principal_internalize()	- Internalize the krb5_principal.
135 */
136static krb5_error_code
137krb5_principal_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
138{
139    krb5_error_code	kret;
140    krb5_principal	principal;
141    krb5_int32		ibuf;
142    krb5_octet		*bp;
143    size_t		remain;
144    char		*tmpname;
145    /* Solaris Kerberos */
146    int			tmpsize;
147    bp = *buffer;
148    remain = *lenremain;
149    kret = EINVAL;
150    /* Read our magic number */
151    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
152	ibuf = 0;
153    if (ibuf == KV5M_PRINCIPAL) {
154	kret = ENOMEM;
155
156	/* See if we have enough data for the length */
157	if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) {
158	    /* Get the string */
159	    /* Solaris Kerberos */
160	    tmpsize = ibuf+1;
161	    tmpname = (char *) MALLOC(tmpsize);
162	    if ((tmpname) &&
163		!(kret = krb5_ser_unpack_bytes((krb5_octet *) tmpname,
164					       (size_t) ibuf,
165					       &bp, &remain))) {
166		tmpname[ibuf] = '\0';
167
168		/* Parse the name to a principal structure */
169		principal = (krb5_principal) NULL;
170		kret = krb5_parse_name(kcontext, tmpname, &principal);
171		if (!kret) {
172		    kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
173		    if (!kret && (ibuf == KV5M_PRINCIPAL)) {
174			*buffer = bp;
175			*lenremain = remain;
176			*argp = principal;
177		    }
178		    else
179			kret = EINVAL;
180		}
181		if (kret && principal)
182		    krb5_free_principal(kcontext, principal);
183		/* Solaris Kerberos */
184		FREE(tmpname,tmpsize);
185	    }
186	}
187    }
188    return(kret);
189}
190
191/*
192 * Register the context serializer.
193 */
194krb5_error_code
195krb5_ser_principal_init(krb5_context kcontext)
196{
197    return(krb5_register_serializer(kcontext, &krb5_principal_ser_entry));
198}
199