1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 #include "kdb_ldap.h"
9 #include "ldap_principal.h"
10 #include "princ_xdr.h"
11 #include <kadm5/admin.h>
12 
13 bool_t
ldap_xdr_krb5_ui_2(XDR * xdrs,krb5_ui_2 * objp)14 ldap_xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp)
15 {
16     unsigned int tmp;
17 
18     tmp = (unsigned int) *objp;
19 
20     if (!xdr_u_int(xdrs, &tmp))
21 	return(FALSE);
22 
23     *objp = (krb5_ui_2) tmp;
24     return(TRUE);
25 }
26 
27 bool_t
ldap_xdr_krb5_int16(XDR * xdrs,krb5_int16 * objp)28 ldap_xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp)
29 {
30     int tmp;
31 
32     tmp = (int) *objp;
33 
34     if (!xdr_int(xdrs, &tmp))
35 	return(FALSE);
36 
37     *objp = (krb5_int16) tmp;
38     return(TRUE);
39 }
40 
41 bool_t
ldap_xdr_nullstring(XDR * xdrs,char ** objp)42 ldap_xdr_nullstring(XDR *xdrs, char **objp)
43 {
44     u_int size;
45 
46     if (xdrs->x_op == XDR_ENCODE) {
47 	if (*objp == NULL)
48 	    size = 0;
49 	else
50 	    size = strlen(*objp) + 1;
51     }
52     if (! xdr_u_int(xdrs, &size)) {
53 	return FALSE;
54     }
55     switch (xdrs->x_op) {
56     case XDR_DECODE:
57 	if (size == 0) {
58 	    *objp = NULL;
59 	    return TRUE;
60 	} else if (*objp == NULL) {
61 	    *objp = (char *) mem_alloc(size);
62 	    if (*objp == NULL) {
63 		/*errno = ENOMEM;*/
64 		return FALSE;
65 	    }
66 	}
67 	return (xdr_opaque(xdrs, *objp, size));
68 
69     case XDR_ENCODE:
70 	if (size != 0)
71 	    return (xdr_opaque(xdrs, *objp, size));
72 	return TRUE;
73 
74     case XDR_FREE:
75 	if (*objp != NULL)
76 	    mem_free(*objp, size);
77 	*objp = NULL;
78 	return TRUE;
79     }
80     return FALSE;
81 }
82 
83 bool_t
ldap_xdr_krb5_kvno(XDR * xdrs,krb5_kvno * objp)84 ldap_xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp)
85 {
86     unsigned char tmp;
87 
88     tmp = '\0'; /* for purify, else xdr_u_char performs a umr */
89 
90     if (xdrs->x_op == XDR_ENCODE)
91 	tmp = (unsigned char) *objp;
92 
93     if (!xdr_u_char(xdrs, &tmp))
94 	return (FALSE);
95 
96     if (xdrs->x_op == XDR_DECODE)
97 	*objp = (krb5_kvno) tmp;
98     return (TRUE);
99 }
100 
101 bool_t
ldap_xdr_krb5_key_data(XDR * xdrs,krb5_key_data * objp)102 ldap_xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp)
103 {
104     unsigned int tmp;
105 
106     if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_ver))
107 	return(FALSE);
108     if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_kvno))
109 	return(FALSE);
110     if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_type[0]))
111 	return(FALSE);
112     if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_type[1]))
113 	return(FALSE);
114     /*
115      * Solaris kerberos: need this cast for now, should go away when kdb.h is
116      * resynced.
117      */
118     if (!ldap_xdr_krb5_ui_2(xdrs, (krb5_ui_2 *)&objp->key_data_length[0]))
119 	return(FALSE);
120     if (!ldap_xdr_krb5_ui_2(xdrs, (krb5_ui_2 *)&objp->key_data_length[1]))
121 	return(FALSE);
122 
123     tmp = (unsigned int) objp->key_data_length[0];
124     if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0],
125 		   &tmp, (unsigned int) ~0))
126 	return FALSE;
127 
128     tmp = (unsigned int) objp->key_data_length[1];
129     if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1],
130 		   &tmp, (unsigned int) ~0))
131 	return FALSE;
132 
133     /* don't need to copy tmp out, since key_data_length will be set
134        by the above encoding. */
135     return(TRUE);
136 }
137 
138 bool_t
ldap_xdr_osa_pw_hist_ent(XDR * xdrs,osa_pw_hist_ent * objp)139 ldap_xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp)
140 {
141     if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
142 		   (u_int *) &objp->n_key_data, (unsigned int) ~0,
143 		   sizeof(krb5_key_data),
144 		   ldap_xdr_krb5_key_data))
145 	return (FALSE);
146     return (TRUE);
147 }
148 
149 bool_t
ldap_xdr_osa_princ_ent_rec(XDR * xdrs,osa_princ_ent_t objp)150 ldap_xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp)
151 {
152     switch (xdrs->x_op) {
153     case XDR_ENCODE:
154 	objp->version = OSA_ADB_PRINC_VERSION_1;
155 	/* fall through */
156     /*LINTED*/
157     case XDR_FREE:
158 	if (!xdr_int(xdrs, &objp->version))
159 	    return FALSE;
160 	break;
161     case XDR_DECODE:
162 	if (!xdr_int(xdrs, &objp->version))
163 	    return FALSE;
164 	if (objp->version != OSA_ADB_PRINC_VERSION_1)
165 	    return FALSE;
166 	break;
167     }
168 
169     if (!ldap_xdr_nullstring(xdrs, &objp->policy))
170 	return (FALSE);
171     if (!xdr_long(xdrs, &objp->aux_attributes))
172 	return (FALSE);
173     if (!xdr_u_int(xdrs, &objp->old_key_next))
174 	return (FALSE);
175     if (!ldap_xdr_krb5_kvno(xdrs, &objp->admin_history_kvno))
176 	return (FALSE);
177     if (!xdr_array(xdrs, (caddr_t *) &objp->old_keys,
178 		   (unsigned int *) &objp->old_key_len, (unsigned int) ~0,
179 		   sizeof(osa_pw_hist_ent),
180 		   ldap_xdr_osa_pw_hist_ent))
181 	return (FALSE);
182     return (TRUE);
183 }
184 
185 void
ldap_osa_free_princ_ent(osa_princ_ent_t val)186 ldap_osa_free_princ_ent(osa_princ_ent_t val)
187 {
188     XDR xdrs;
189 
190     xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
191 
192     ldap_xdr_osa_princ_ent_rec(&xdrs, val);
193     free(val);
194 }
195 
196 krb5_error_code
krb5_lookup_tl_kadm_data(krb5_tl_data * tl_data,osa_princ_ent_rec * princ_entry)197 krb5_lookup_tl_kadm_data(krb5_tl_data *tl_data, osa_princ_ent_rec *princ_entry)
198 {
199 
200     XDR xdrs;
201 
202     xdrmem_create(&xdrs, (const caddr_t)tl_data->tl_data_contents,
203 		  tl_data->tl_data_length, XDR_DECODE);
204     if (! ldap_xdr_osa_princ_ent_rec(&xdrs, princ_entry)) {
205 	xdr_destroy(&xdrs);
206 	return(KADM5_XDR_FAILURE);
207     }
208     xdr_destroy(&xdrs);
209 
210     return 0;
211 
212 }
213 
214 krb5_error_code
krb5_update_tl_kadm_data(policy_dn,new_tl_data,old_tl_data)215 krb5_update_tl_kadm_data(policy_dn, new_tl_data, old_tl_data)
216     char	        * policy_dn;
217     krb5_tl_data        * new_tl_data;
218     /* Solaris Kerberos: adding support for key history in LDAP KDB */
219     krb5_tl_data        * old_tl_data;
220 {
221     XDR xdrs;
222     osa_princ_ent_t princ_entry;
223     /* Solaris Kerberos: added the next line to fix a memleak. */
224     char *tmpbuf;
225 
226     if ((princ_entry = (osa_princ_ent_t) malloc(sizeof(osa_princ_ent_rec))) == NULL)
227 	return ENOMEM;
228 
229     memset(princ_entry, 0, sizeof(osa_princ_ent_rec));
230     princ_entry->aux_attributes = KADM5_POLICY;
231 
232     /* Solaris Kerberos: adding support for key history in LDAP KDB */
233     if (old_tl_data != NULL) {
234 	/* get the key history from the old tl_data */
235 	xdrmem_create(&xdrs, (caddr_t)old_tl_data->tl_data_contents,
236 	    old_tl_data->tl_data_length, XDR_DECODE);
237 	if (! ldap_xdr_osa_princ_ent_rec(&xdrs, princ_entry)) {
238 	    xdr_destroy(&xdrs);
239 	    free(princ_entry);
240 	    return(KADM5_XDR_FAILURE);
241 	}
242 	xdr_destroy(&xdrs);
243 	/* will set the policy field further down, avoid mem leak */
244 	free(princ_entry->policy);
245     } else {
246 	princ_entry->admin_history_kvno = 2;
247     }
248     princ_entry->policy = policy_dn;
249 
250     xdralloc_create(&xdrs, XDR_ENCODE);
251     if (! ldap_xdr_osa_princ_ent_rec(&xdrs, princ_entry)) {
252 	xdr_destroy(&xdrs);
253 	free(princ_entry);
254 	return(KADM5_XDR_FAILURE);
255     }
256     new_tl_data->tl_data_type = KRB5_TL_KADM_DATA;
257     new_tl_data->tl_data_length = xdr_getpos(&xdrs);
258     /* Solaris Kerberos: added the next line to fix a memleak. */
259     if ((tmpbuf = (char *) malloc(new_tl_data->tl_data_length)) == NULL)
260 	return ENOMEM;
261     memcpy(tmpbuf, xdralloc_getdata(&xdrs), new_tl_data->tl_data_length);
262     new_tl_data->tl_data_contents = (krb5_octet *)tmpbuf;
263 
264     /* Solaris Kerberos: added the next lines to fix a memleak. */
265     free(princ_entry);
266     xdr_destroy(&xdrs);
267 
268     return(0);
269 }
270