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  */
46 static krb5_error_code krb5_principal_size
47 	(krb5_context, krb5_pointer, size_t *);
48 static krb5_error_code krb5_principal_externalize
49 	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
50 static krb5_error_code krb5_principal_internalize
51 	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
52 
53 /* Local data */
54 static 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  */
65 static krb5_error_code
krb5_principal_size(krb5_context kcontext,krb5_pointer arg,size_t * sizep)66 krb5_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  */
94 static krb5_error_code
krb5_principal_externalize(krb5_context kcontext,krb5_pointer arg,krb5_octet ** buffer,size_t * lenremain)95 krb5_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  */
136 static krb5_error_code
krb5_principal_internalize(krb5_context kcontext,krb5_pointer * argp,krb5_octet ** buffer,size_t * lenremain)137 krb5_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  */
194 krb5_error_code
krb5_ser_principal_init(krb5_context kcontext)195 krb5_ser_principal_init(krb5_context kcontext)
196 {
197     return(krb5_register_serializer(kcontext, &krb5_principal_ser_entry));
198 }
199