1*54925bf6Swillf #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*54925bf6Swillf 
3*54925bf6Swillf /*
4*54925bf6Swillf  * lib/kdb/kdb_ldap/kdb_xdr.c
5*54925bf6Swillf  *
6*54925bf6Swillf  * Copyright 1995 by the Massachusetts Institute of Technology.
7*54925bf6Swillf  * All Rights Reserved.
8*54925bf6Swillf  *
9*54925bf6Swillf  * Export of this software from the United States of America may
10*54925bf6Swillf  *   require a specific license from the United States Government.
11*54925bf6Swillf  *   It is the responsibility of any person or organization contemplating
12*54925bf6Swillf  *   export to obtain such a license before exporting.
13*54925bf6Swillf  *
14*54925bf6Swillf  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
15*54925bf6Swillf  * distribute this software and its documentation for any purpose and
16*54925bf6Swillf  * without fee is hereby granted, provided that the above copyright
17*54925bf6Swillf  * notice appear in all copies and that both that copyright notice and
18*54925bf6Swillf  * this permission notice appear in supporting documentation, and that
19*54925bf6Swillf  * the name of M.I.T. not be used in advertising or publicity pertaining
20*54925bf6Swillf  * to distribution of the software without specific, written prior
21*54925bf6Swillf  * permission.  Furthermore if you modify this software you must label
22*54925bf6Swillf  * your software as modified software and not distribute it in such a
23*54925bf6Swillf  * fashion that it might be confused with the original M.I.T. software.
24*54925bf6Swillf  * M.I.T. makes no representations about the suitability of
25*54925bf6Swillf  * this software for any purpose.  It is provided "as is" without express
26*54925bf6Swillf  * or implied warranty.
27*54925bf6Swillf  *
28*54925bf6Swillf  */
29*54925bf6Swillf 
30*54925bf6Swillf #include <k5-int.h>
31*54925bf6Swillf #include <string.h>
32*54925bf6Swillf #include <stdio.h>
33*54925bf6Swillf #include <errno.h>
34*54925bf6Swillf #include "kdb_xdr.h"
35*54925bf6Swillf 
36*54925bf6Swillf #define safe_realloc(p,n) ((p)?(realloc(p,n)):(malloc(n)))
37*54925bf6Swillf 
38*54925bf6Swillf krb5_error_code
39*54925bf6Swillf krb5_dbe_update_tl_data(context, entry, new_tl_data)
40*54925bf6Swillf     krb5_context          context;
41*54925bf6Swillf     krb5_db_entry       * entry;
42*54925bf6Swillf     krb5_tl_data	* new_tl_data;
43*54925bf6Swillf {
44*54925bf6Swillf     krb5_tl_data        * tl_data;
45*54925bf6Swillf     krb5_octet          * tmp;
46*54925bf6Swillf 
47*54925bf6Swillf     /* copy the new data first, so we can fail cleanly if malloc()
48*54925bf6Swillf        fails */
49*54925bf6Swillf 
50*54925bf6Swillf     if ((tmp = (krb5_octet *) malloc(new_tl_data->tl_data_length)) == NULL)
51*54925bf6Swillf 	return(ENOMEM);
52*54925bf6Swillf 
53*54925bf6Swillf     /* Find an existing entry of the specified type and point at
54*54925bf6Swillf        it, or NULL if not found */
55*54925bf6Swillf 
56*54925bf6Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next)
57*54925bf6Swillf 	if (tl_data->tl_data_type == new_tl_data->tl_data_type)
58*54925bf6Swillf 	    break;
59*54925bf6Swillf 
60*54925bf6Swillf     /* if necessary, chain a new record in the beginning and point at it */
61*54925bf6Swillf 
62*54925bf6Swillf     if (!tl_data) {
63*54925bf6Swillf 	if ((tl_data = (krb5_tl_data *) calloc(1, sizeof(krb5_tl_data)))
64*54925bf6Swillf 	    == NULL) {
65*54925bf6Swillf 	    free(tmp);
66*54925bf6Swillf 	    return(ENOMEM);
67*54925bf6Swillf 	}
68*54925bf6Swillf 	tl_data->tl_data_next = entry->tl_data;
69*54925bf6Swillf 	entry->tl_data = tl_data;
70*54925bf6Swillf 	entry->n_tl_data++;
71*54925bf6Swillf     }
72*54925bf6Swillf 
73*54925bf6Swillf     /* fill in the record */
74*54925bf6Swillf 
75*54925bf6Swillf     if (tl_data->tl_data_contents)
76*54925bf6Swillf 	free(tl_data->tl_data_contents);
77*54925bf6Swillf 
78*54925bf6Swillf     tl_data->tl_data_type = new_tl_data->tl_data_type;
79*54925bf6Swillf     tl_data->tl_data_length = new_tl_data->tl_data_length;
80*54925bf6Swillf     tl_data->tl_data_contents = tmp;
81*54925bf6Swillf     memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
82*54925bf6Swillf 
83*54925bf6Swillf     return(0);
84*54925bf6Swillf }
85*54925bf6Swillf 
86*54925bf6Swillf krb5_error_code
87*54925bf6Swillf krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
88*54925bf6Swillf     krb5_context          context;
89*54925bf6Swillf     krb5_db_entry       * entry;
90*54925bf6Swillf     krb5_tl_data        * ret_tl_data;
91*54925bf6Swillf {
92*54925bf6Swillf     krb5_tl_data *tl_data;
93*54925bf6Swillf 
94*54925bf6Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
95*54925bf6Swillf 	if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
96*54925bf6Swillf 	    *ret_tl_data = *tl_data;
97*54925bf6Swillf 	    return(0);
98*54925bf6Swillf 	}
99*54925bf6Swillf     }
100*54925bf6Swillf 
101*54925bf6Swillf     /* if the requested record isn't found, return zero bytes.
102*54925bf6Swillf        if it ever means something to have a zero-length tl_data,
103*54925bf6Swillf        this code and its callers will have to be changed */
104*54925bf6Swillf 
105*54925bf6Swillf     ret_tl_data->tl_data_length = 0;
106*54925bf6Swillf     ret_tl_data->tl_data_contents = NULL;
107*54925bf6Swillf     return(0);
108*54925bf6Swillf }
109*54925bf6Swillf 
110*54925bf6Swillf krb5_error_code
111*54925bf6Swillf krb5_dbe_update_last_pwd_change(context, entry, stamp)
112*54925bf6Swillf     krb5_context          context;
113*54925bf6Swillf     krb5_db_entry       * entry;
114*54925bf6Swillf     krb5_timestamp	  stamp;
115*54925bf6Swillf {
116*54925bf6Swillf     krb5_tl_data        tl_data;
117*54925bf6Swillf     krb5_octet          buf[4]; /* this is the encoded size of an int32 */
118*54925bf6Swillf 
119*54925bf6Swillf     tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
120*54925bf6Swillf     tl_data.tl_data_length = sizeof(buf);
121*54925bf6Swillf     krb5_kdb_encode_int32((krb5_int32) stamp, buf);
122*54925bf6Swillf     tl_data.tl_data_contents = buf;
123*54925bf6Swillf 
124*54925bf6Swillf     return(krb5_dbe_update_tl_data(context, entry, &tl_data));
125*54925bf6Swillf }
126*54925bf6Swillf 
127*54925bf6Swillf krb5_error_code
128*54925bf6Swillf krb5_dbe_lookup_last_pwd_change(context, entry, stamp)
129*54925bf6Swillf     krb5_context          context;
130*54925bf6Swillf     krb5_db_entry       * entry;
131*54925bf6Swillf     krb5_timestamp	* stamp;
132*54925bf6Swillf {
133*54925bf6Swillf     krb5_tl_data        tl_data;
134*54925bf6Swillf     krb5_error_code	code;
135*54925bf6Swillf     krb5_int32		tmp;
136*54925bf6Swillf 
137*54925bf6Swillf     tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
138*54925bf6Swillf 
139*54925bf6Swillf     if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
140*54925bf6Swillf 	return(code);
141*54925bf6Swillf 
142*54925bf6Swillf     if (tl_data.tl_data_length != 4) {
143*54925bf6Swillf 	*stamp = 0;
144*54925bf6Swillf 	return(0);
145*54925bf6Swillf     }
146*54925bf6Swillf 
147*54925bf6Swillf     krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
148*54925bf6Swillf 
149*54925bf6Swillf     *stamp = (krb5_timestamp) tmp;
150*54925bf6Swillf 
151*54925bf6Swillf     return(0);
152*54925bf6Swillf }
153*54925bf6Swillf 
154*54925bf6Swillf /* it seems odd that there's no function to remove a tl_data, but if
155*54925bf6Swillf    I need one, I'll add one */
156*54925bf6Swillf 
157*54925bf6Swillf krb5_error_code
158*54925bf6Swillf krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
159*54925bf6Swillf     krb5_context	  context;
160*54925bf6Swillf     krb5_db_entry	* entry;
161*54925bf6Swillf     krb5_timestamp	  mod_date;
162*54925bf6Swillf     krb5_const_principal  mod_princ;
163*54925bf6Swillf {
164*54925bf6Swillf     krb5_tl_data          tl_data;
165*54925bf6Swillf 
166*54925bf6Swillf     krb5_error_code 	  retval = 0;
167*54925bf6Swillf     krb5_octet		* nextloc = 0;
168*54925bf6Swillf     char		* unparse_mod_princ = 0;
169*54925bf6Swillf     unsigned int	unparse_mod_princ_size;
170*54925bf6Swillf 
171*54925bf6Swillf     if ((retval = krb5_unparse_name(context, mod_princ,
172*54925bf6Swillf 				    &unparse_mod_princ)))
173*54925bf6Swillf 	return(retval);
174*54925bf6Swillf 
175*54925bf6Swillf     unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
176*54925bf6Swillf 
177*54925bf6Swillf     if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
178*54925bf6Swillf 	== NULL) {
179*54925bf6Swillf 	free(unparse_mod_princ);
180*54925bf6Swillf 	return(ENOMEM);
181*54925bf6Swillf     }
182*54925bf6Swillf 
183*54925bf6Swillf     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
184*54925bf6Swillf     tl_data.tl_data_length = unparse_mod_princ_size + 4;
185*54925bf6Swillf     tl_data.tl_data_contents = nextloc;
186*54925bf6Swillf 
187*54925bf6Swillf     /* Mod Date */
188*54925bf6Swillf     krb5_kdb_encode_int32(mod_date, nextloc);
189*54925bf6Swillf 
190*54925bf6Swillf     /* Mod Princ */
191*54925bf6Swillf     memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);
192*54925bf6Swillf 
193*54925bf6Swillf     retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
194*54925bf6Swillf 
195*54925bf6Swillf     free(unparse_mod_princ);
196*54925bf6Swillf     free(nextloc);
197*54925bf6Swillf 
198*54925bf6Swillf     return(retval);
199*54925bf6Swillf }
200*54925bf6Swillf 
201*54925bf6Swillf krb5_error_code
202*54925bf6Swillf krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
203*54925bf6Swillf     krb5_context	  context;
204*54925bf6Swillf     krb5_db_entry	* entry;
205*54925bf6Swillf     krb5_timestamp	* mod_time;
206*54925bf6Swillf     krb5_principal	* mod_princ;
207*54925bf6Swillf {
208*54925bf6Swillf     krb5_tl_data        tl_data;
209*54925bf6Swillf     krb5_error_code	code;
210*54925bf6Swillf 
211*54925bf6Swillf     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
212*54925bf6Swillf 
213*54925bf6Swillf     if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
214*54925bf6Swillf 	return(code);
215*54925bf6Swillf 
216*54925bf6Swillf     if ((tl_data.tl_data_length < 5) ||
217*54925bf6Swillf 	(tl_data.tl_data_contents[tl_data.tl_data_length-1] != '\0'))
218*54925bf6Swillf 	return(KRB5_KDB_TRUNCATED_RECORD);
219*54925bf6Swillf 
220*54925bf6Swillf     /* Mod Date */
221*54925bf6Swillf     krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
222*54925bf6Swillf 
223*54925bf6Swillf     /* Mod Princ */
224*54925bf6Swillf     if ((code = krb5_parse_name(context,
225*54925bf6Swillf 				(const char *) (tl_data.tl_data_contents+4),
226*54925bf6Swillf 				mod_princ)))
227*54925bf6Swillf 	return(code);
228*54925bf6Swillf 
229*54925bf6Swillf     return(0);
230*54925bf6Swillf }
231