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