Sdiff kdb_db2.c
  1 /*
  2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  3  * Use is subject to license terms.
  4  */
  5 
  6 #pragma ident   "@(#)kdb_db2.c  1.4     04/09/08 SMI" 
  7 
  8 /*
  9  * lib/kdb/kdb_db2.c
 10  *
 11  * Copyright 1997 by the Massachusetts Institute of Technology.
 12  * All Rights Reserved.
 13  *
 14  * Export of this software from the United States of America may
 15  *   require a specific license from the United States Government.
 16  *   It is the responsibility of any person or organization contemplating
 17  *   export to obtain such a license before exporting.
 18  * 
 19  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 20  * distribute this software and its documentation for any purpose and
 21  * without fee is hereby granted, provided that the above copyright
 22  * notice appear in all copies and that both that copyright notice and
 23  * this permission notice appear in supporting documentation, and that
 24  * the name of M.I.T. not be used in advertising or publicity pertaining
 25  * to distribution of the software without specific, written prior
 26  * permission.  Furthermore if you modify this software you must label


46 * distribute this software and its documentation for any purpose and 47 * without fee is hereby granted, provided that the above copyright 48 * notice appear in all copies and that both that copyright notice and 49 * this permission notice appear in supporting documentation, and that 50 * the name of FundsXpress. not be used in advertising or publicity pertaining 51 * to distribution of the software without specific, written prior 52 * permission. FundsXpress makes no representations about the suitability of 53 * this software for any purpose. It is provided "as is" without express 54 * or implied warranty. 55 * 56 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 57 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 58 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 59 */ 60 61 #if HAVE_UNISTD_H 62 #include <unistd.h> 63 #endif 64 65 #include "k5-int.h" 66 #include <db.h> 67 #include <stdio.h> 68 #include <errno.h> 69 #include <utime.h> 70 71 #define OLD_COMPAT_VERSION_1 72 73 #ifdef OLD_COMPAT_VERSION_1 74 #include "kdb_compat.h" 75 #endif 76 77 #include "kdb_db2.h" 78 79 static char *gen_dbsuffix 80 PROTOTYPE((char *, char * )); 81 static krb5_error_code krb5_db2_db_start_update 82 PROTOTYPE((krb5_context)); 83 static krb5_error_code krb5_db2_db_end_update 84 PROTOTYPE((krb5_context)); 85 static krb5_error_code krb5_db2_db_set_hashfirst
970 database. 971 972 *"nentries" is updated upon return to reflect the number of records 973 acutally stored; the first *"nstored" records will have been stored in the 974 database (even if an error occurs). 975 976 */ 977 978 krb5_error_code 979 krb5_db2_db_put_principal(context, entries, nentries) 980 krb5_context context; 981 krb5_db_entry *entries; 982 register int *nentries; /* number of entry structs to update */ 983 { 984 int i, n, dbret; 985 DB *db; 986 DBT key, contents; 987 krb5_data contdata, keydata; 988 krb5_error_code retval; 989 krb5_db2_context *db_ctx; 990 991 n = *nentries; 992 *nentries = 0; 993 if (!k5db2_inited(context)) 994 return KRB5_KDB_DBNOTINITED; 995 996 db_ctx = (krb5_db2_context *) context->db_context; 997 if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE))) 998 return retval; 999 1000 db = db_ctx->db; 1001 if ((retval = krb5_db2_db_start_update(context))) { 1002 (void)krb5_db2_db_unlock(context); 1003 return retval; 1004 } 1005 1006 /* for each one, stuff temps, and do replace/append */ 1007 for (i = 0; i < n; i++) { 1008 retval = krb5_encode_princ_contents(context, &contdata, entries); 1009 if (retval) 1010 break; 1011 contents.data = contdata.data; 1012 contents.size = contdata.length; 1013 retval = krb5_encode_princ_dbkey(context, &keydata, entries->princ); 1014 if (retval) { 1015 krb5_free_data_contents(context, &contdata); 1016 break; 1017 } 1018 1019 key.data = keydata.data; 1020 key.size = keydata.length; 1021 dbret = (*db->put)(db, &key, &contents, 0); 1022 retval = dbret ? errno : 0; 1023 krb5_free_data_contents(context, &keydata); 1024 krb5_free_data_contents(context, &contdata); 1025 if (retval) 1026 break; 1027 entries++; /* bump to next struct */ 1028 } 1029 1030 (void)krb5_db2_db_end_update(context); 1031 (void)krb5_db2_db_unlock(context); /* unlock database */ 1032 *nentries = i; 1033 return(retval); 1034 } 1035 1036 /* 1037 * delete a principal from the data base. 1038 * returns number of entries removed 1039 */ 1040 1041 krb5_error_code 1042 krb5_db2_db_delete_principal(context, searchfor, nentries) 1043 krb5_context context; 1044 krb5_const_principal searchfor; 1045 int *nentries; /* how many found & deleted */ 1046 { 1047 krb5_error_code retval; 1048 krb5_db_entry entry; 1049 krb5_db2_context *db_ctx; 1050 DB *db; 1051 DBT key, contents; 1052 krb5_data keydata, contdata; 1053 int i, dbret; 1054 1055 if (!k5db2_inited(context)) 1056 return KRB5_KDB_DBNOTINITED; 1057 1058 db_ctx = (krb5_db2_context *) context->db_context; 1059 if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE))) 1060 return(retval); 1061 1062 if ((retval = krb5_db2_db_start_update(context))) { 1063 (void) krb5_db2_db_unlock(context); /* unlock write lock */ 1064 return(retval); 1065 } 1066 1067 if ((retval = krb5_encode_princ_dbkey(context, &keydata, searchfor))) 1068 goto cleanup; 1069 key.data = keydata.data; 1070 key.size = keydata.length; 1071 1072 db = db_ctx->db; 1073 dbret = (*db->get)(db, &key, &contents, 0); 1074 retval = errno; 1075 switch (dbret) { 1076 case 1: 1077 retval = KRB5_KDB_NOENTRY; 1078 case -1: 1079 default: 1080 *nentries = 0; 1081 goto cleankey; 1082 case 0: 1083 ; 1084 } 1085 memset((char *)&entry, 0, sizeof(entry)); 1086 contdata.data = contents.data; 1087 contdata.length = contents.size; 1088 retval = krb5_decode_princ_contents(context, &contdata, &entry); 1089 if (retval) 1090 goto cleankey; 1091 *nentries = 1; 1092 1093 /* Clear encrypted key contents */ 1094 for (i = 0; i < entry.n_key_data; i++) { 1095 if (entry.key_data[i].key_data_length[0]) { 1096 memset((char *)entry.key_data[i].key_data_contents[0], 0, 1097 entry.key_data[i].key_data_length[0]); 1098 } 1099 } 1100 1101 retval = krb5_encode_princ_contents(context, &contdata, &entry); 1102 krb5_dbe_free_contents(context, &entry); 1103 if (retval) 1104 goto cleankey; 1105 1106 contents.data = contdata.data; 1107 contents.size = contdata.length; 1108 dbret = (*db->put)(db, &key, &contents, 0); 1109 retval = dbret ? errno : 0; 1110 krb5_free_data_contents(context, &contdata); 1111 if (retval) 1112 goto cleankey; 1113 dbret = (*db->del)(db, &key, 0); 1114 retval = dbret ? errno : 0; 1115 cleankey: 1116 krb5_free_data_contents(context, &keydata); 1117 1118 cleanup: 1119 (void) krb5_db2_db_end_update(context); 1120 (void) krb5_db2_db_unlock(context); /* unlock write lock */ 1121 return retval; 1122 } 1123 1124 krb5_error_code 1125 krb5_db2_db_iterate (context, func, func_arg) 1126 krb5_context context; 1127 krb5_error_code (*func) PROTOTYPE((krb5_pointer, krb5_db_entry *)); 1128 krb5_pointer func_arg; 1129 { 1130 krb5_db2_context *db_ctx; 1131 DB *db; 1132 DBT key, contents; 1133 krb5_data contdata; 1134 krb5_db_entry entries;
  1 /*
  2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  3  * Use is subject to license terms.
  4  */
  5 
  6 #pragma ident   "@(#)kdb_db2.c  1.3     04/02/20 SMI" 
  7 
  8 /*
  9  * lib/kdb/kdb_db2.c
 10  *
 11  * Copyright 1997 by the Massachusetts Institute of Technology.
 12  * All Rights Reserved.
 13  *
 14  * Export of this software from the United States of America may
 15  *   require a specific license from the United States Government.
 16  *   It is the responsibility of any person or organization contemplating
 17  *   export to obtain such a license before exporting.
 18  * 
 19  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 20  * distribute this software and its documentation for any purpose and
 21  * without fee is hereby granted, provided that the above copyright
 22  * notice appear in all copies and that both that copyright notice and
 23  * this permission notice appear in supporting documentation, and that
 24  * the name of M.I.T. not be used in advertising or publicity pertaining
 25  * to distribution of the software without specific, written prior
 26  * permission.  Furthermore if you modify this software you must label


46 * distribute this software and its documentation for any purpose and 47 * without fee is hereby granted, provided that the above copyright 48 * notice appear in all copies and that both that copyright notice and 49 * this permission notice appear in supporting documentation, and that 50 * the name of FundsXpress. not be used in advertising or publicity pertaining 51 * to distribution of the software without specific, written prior 52 * permission. FundsXpress makes no representations about the suitability of 53 * this software for any purpose. It is provided "as is" without express 54 * or implied warranty. 55 * 56 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 57 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 58 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 59 */ 60 61 #if HAVE_UNISTD_H 62 #include <unistd.h> 63 #endif 64 65 #include "k5-int.h" 66 #include "kdb_log.h" 67 #include <db.h> 68 #include <stdio.h> 69 #include <errno.h> 70 #include <utime.h> 71 72 #define OLD_COMPAT_VERSION_1 73 74 #ifdef OLD_COMPAT_VERSION_1 75 #include "kdb_compat.h" 76 #endif 77 78 #include "kdb_db2.h" 79 80 static char *gen_dbsuffix 81 PROTOTYPE((char *, char * )); 82 static krb5_error_code krb5_db2_db_start_update 83 PROTOTYPE((krb5_context)); 84 static krb5_error_code krb5_db2_db_end_update 85 PROTOTYPE((krb5_context)); 86 static krb5_error_code krb5_db2_db_set_hashfirst
971 database. 972 973 *"nentries" is updated upon return to reflect the number of records 974 acutally stored; the first *"nstored" records will have been stored in the 975 database (even if an error occurs). 976 977 */ 978 979 krb5_error_code 980 krb5_db2_db_put_principal(context, entries, nentries) 981 krb5_context context; 982 krb5_db_entry *entries; 983 register int *nentries; /* number of entry structs to update */ 984 { 985 int i, n, dbret; 986 DB *db; 987 DBT key, contents; 988 krb5_data contdata, keydata; 989 krb5_error_code retval; 990 krb5_db2_context *db_ctx; 991 kdb_incr_update_t *upd, *fupd; 992 char *princ_name = NULL; 993 kdb_log_context *log_ctx; 994 995 log_ctx = context->kdblog_context; 996 997 n = *nentries; 998 *nentries = 0; 999 if (!k5db2_inited(context)) 1000 return KRB5_KDB_DBNOTINITED; 1001 1002 db_ctx = (krb5_db2_context *) context->db_context; 1003 if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE))) { 1004 return retval; 1005 } 1006 1007 /* 1008 * We need the lock since ulog_conv_2logentry() does a get 1009 */ 1010 if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) { 1011 if (!(upd = (kdb_incr_update_t *) 1012 malloc(sizeof (kdb_incr_update_t)*n))) { 1013 retval = errno; 1014 goto err_lock; 1015 } 1016 fupd = upd; 1017 1018 (void) memset(upd, 0, sizeof(kdb_incr_update_t)*n); 1019 1020 if ((retval = ulog_conv_2logentry(context, entries, upd, n))) { 1021 goto err_lock; 1022 } 1023 } 1024 1025 db = db_ctx->db; 1026 if ((retval = krb5_db2_db_start_update(context))) { 1027 goto err_lock; 1028 } 1029 1030 /* for each one, stuff temps, and do replace/append */ 1031 for (i = 0; i < n; i++) { 1032 /* 1033 * We'll be sharing the same locks as db for logging 1034 */ 1035 if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) { 1036 if ((retval = krb5_unparse_name(context, entries->princ, 1037 &princ_name))) 1038 goto err_lock; 1039 1040 upd->kdb_princ_name.utf8str_t_val = princ_name; 1041 upd->kdb_princ_name.utf8str_t_len = strlen(princ_name); 1042 1043 if (retval = ulog_add_update(context, upd)) 1044 goto err_lock; 1045 } 1046 1047 retval = krb5_encode_princ_contents(context, &contdata, entries); 1048 if (retval) 1049 break; 1050 contents.data = contdata.data; 1051 contents.size = contdata.length; 1052 retval = krb5_encode_princ_dbkey(context, &keydata, entries->princ); 1053 if (retval) { 1054 krb5_free_data_contents(context, &contdata); 1055 break; 1056 } 1057 1058 key.data = keydata.data; 1059 key.size = keydata.length; 1060 dbret = (*db->put)(db, &key, &contents, 0); 1061 retval = dbret ? errno : 0; 1062 krb5_free_data_contents(context, &keydata); 1063 krb5_free_data_contents(context, &contdata); 1064 if (retval) 1065 break; 1066 else if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) { 1067 /* 1068 * We need to make sure the db record is synced before we mark 1069 * it as committed via finish_update. 1070 */ 1071 dbret = (*db->sync)(db, 0); 1072 if (dbret) { 1073 retval = errno; 1074 goto err_lock; 1075 } 1076 (void) ulog_finish_update(context, upd); 1077 upd++; 1078 } 1079 entries++; /* bump to next struct */ 1080 } 1081 1082 (void)krb5_db2_db_end_update(context); 1083 1084 err_lock: 1085 (void)krb5_db2_db_unlock(context); /* unlock database */ 1086 1087 if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) 1088 ulog_free_entries(fupd, n); 1089 1090 *nentries = i; 1091 return(retval); 1092 } 1093 1094 /* 1095 * delete a principal from the data base. 1096 * returns number of entries removed 1097 */ 1098 1099 krb5_error_code 1100 krb5_db2_db_delete_principal(context, searchfor, nentries) 1101 krb5_context context; 1102 krb5_const_principal searchfor; 1103 int *nentries; /* how many found & deleted */ 1104 { 1105 krb5_error_code retval; 1106 krb5_db_entry entry; 1107 krb5_db2_context *db_ctx; 1108 DB *db; 1109 DBT key, contents; 1110 krb5_data keydata, contdata; 1111 int i, dbret; 1112 kdb_incr_update_t upd; 1113 char *princ_name = NULL; 1114 kdb_log_context *log_ctx; 1115 1116 log_ctx = context->kdblog_context; 1117 1118 if (!k5db2_inited(context)) 1119 return KRB5_KDB_DBNOTINITED; 1120 1121 db_ctx = (krb5_db2_context *) context->db_context; 1122 if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE))) 1123 return(retval); 1124 1125 if ((retval = krb5_db2_db_start_update(context))) { 1126 (void) krb5_db2_db_unlock(context); /* unlock write lock */ 1127 return(retval); 1128 } 1129 1130 if ((retval = krb5_encode_princ_dbkey(context, &keydata, searchfor))) 1131 goto cleanup; 1132 key.data = keydata.data; 1133 key.size = keydata.length; 1134 1135 db = db_ctx->db; 1136 dbret = (*db->get)(db, &key, &contents, 0); 1137 retval = errno; 1138 switch (dbret) { 1139 case 1: 1140 retval = KRB5_KDB_NOENTRY; 1141 case -1: 1142 default: 1143 *nentries = 0; 1144 goto cleankey; 1145 case 0: 1146 ; 1147 } 1148 1149 /* 1150 * We'll be sharing the same locks as db for logging 1151 */ 1152 if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) { 1153 if ((retval = krb5_unparse_name(context, searchfor, &princ_name))) { 1154 (void) krb5_db2_db_unlock(context); 1155 return retval; 1156 } 1157 1158 (void) memset(&upd, 0, sizeof (kdb_incr_update_t)); 1159 1160 upd.kdb_princ_name.utf8str_t_val = princ_name; 1161 upd.kdb_princ_name.utf8str_t_len = strlen(princ_name); 1162 1163 if (retval = ulog_delete_update(context, &upd)) { 1164 free(princ_name); 1165 (void) krb5_db2_db_unlock(context); 1166 return retval; 1167 } 1168 1169 free(princ_name); 1170 } 1171 1172 memset((char *)&entry, 0, sizeof(entry)); 1173 contdata.data = contents.data; 1174 contdata.length = contents.size; 1175 retval = krb5_decode_princ_contents(context, &contdata, &entry); 1176 if (retval) 1177 goto cleankey; 1178 *nentries = 1; 1179 1180 /* Clear encrypted key contents */ 1181 for (i = 0; i < entry.n_key_data; i++) { 1182 if (entry.key_data[i].key_data_length[0]) { 1183 memset((char *)entry.key_data[i].key_data_contents[0], 0, 1184 entry.key_data[i].key_data_length[0]); 1185 } 1186 } 1187 1188 retval = krb5_encode_princ_contents(context, &contdata, &entry); 1189 krb5_dbe_free_contents(context, &entry); 1190 if (retval) 1191 goto cleankey; 1192 1193 contents.data = contdata.data; 1194 contents.size = contdata.length; 1195 dbret = (*db->put)(db, &key, &contents, 0); 1196 retval = dbret ? errno : 0; 1197 krb5_free_data_contents(context, &contdata); 1198 if (retval) 1199 goto cleankey; 1200 dbret = (*db->del)(db, &key, 0); 1201 retval = dbret ? errno : 0; 1202 1203 /* 1204 * We need to commit our update upon success 1205 */ 1206 if (!retval) 1207 if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) 1208 (void) ulog_finish_update(context, &upd); 1209 1210 cleankey: 1211 krb5_free_data_contents(context, &keydata); 1212 1213 cleanup: 1214 (void) krb5_db2_db_end_update(context); 1215 (void) krb5_db2_db_unlock(context); /* unlock write lock */ 1216 return retval; 1217 } 1218 1219 krb5_error_code 1220 krb5_db2_db_iterate (context, func, func_arg) 1221 krb5_context context; 1222 krb5_error_code (*func) PROTOTYPE((krb5_pointer, krb5_db_entry *)); 1223 krb5_pointer func_arg; 1224 { 1225 krb5_db2_context *db_ctx; 1226 DB *db; 1227 DBT key, contents; 1228 krb5_data contdata; 1229 krb5_db_entry entries;