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