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;
|