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