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