3
3
#include < string>
4
4
5
5
#include < fcntl.h>
6
+ #include < unistd.h>
6
7
7
8
#include < rpm/header.h>
8
9
#include < rpm/rpmbase64.h>
@@ -24,11 +25,11 @@ using namespace rpm;
24
25
25
26
static int makePubkeyHeader (rpmts ts, rpmPubkey key, Header * hdrp);
26
27
27
- rpmRC keystore_fs::load_keys (rpmtxn txn, rpmKeyring keyring)
28
+ static rpmRC load_keys_from_glob (rpmtxn txn, rpmKeyring keyring, string glob )
28
29
{
29
30
ARGV_t files = NULL ;
30
31
/* XXX TODO: deal with chroot path issues */
31
- char *pkpath = rpmGetPath (rpmtxnRootDir (txn), " %{_keyringpath}/*.key " , NULL );
32
+ char *pkpath = rpmGetPath (rpmtxnRootDir (txn), glob. c_str () , NULL );
32
33
33
34
rpmlog (RPMLOG_DEBUG, " loading keyring from pubkeys in %s\n " , pkpath);
34
35
if (rpmGlob (pkpath, NULL , &files)) {
@@ -55,6 +56,53 @@ rpmRC keystore_fs::load_keys(rpmtxn txn, rpmKeyring keyring)
55
56
return RPMRC_OK;
56
57
}
57
58
59
+ static rpmRC write_key_to_disk (rpmPubkey key, string & dir, string & filename, int replace, rpmFlags flags)
60
+ {
61
+ rpmRC rc = RPMRC_FAIL;
62
+ char *keyval = rpmPubkeyArmorWrap (key);
63
+ string tmppath = " " ;
64
+ string path = dir + " /" + filename;
65
+
66
+ if (replace) {
67
+ tmppath = dir + " /" + filename + " .new" ;
68
+ unlink (tmppath.c_str ());
69
+ }
70
+
71
+ if (rpmMkdirs (NULL , dir.c_str ())) {
72
+ rpmlog (RPMLOG_ERR, _ (" failed to create keyring directory %s: %s\n " ),
73
+ path.c_str (), strerror (errno));
74
+ goto exit ;
75
+ }
76
+
77
+ if (FD_t fd = Fopen (replace ? tmppath.c_str () : path.c_str (), " wx" )) {
78
+ size_t keylen = strlen (keyval);
79
+ if (Fwrite (keyval, 1 , keylen, fd) == keylen)
80
+ rc = RPMRC_OK;
81
+ Fclose (fd);
82
+ }
83
+ if (!rc && replace && rename (tmppath.c_str (), path.c_str ()) != 0 )
84
+ rc = RPMRC_FAIL;
85
+
86
+ if (rc) {
87
+ rpmlog (RPMLOG_ERR, _ (" failed to import key: %s: %s\n " ),
88
+ replace ? tmppath.c_str () : path.c_str (), strerror (errno));
89
+ if (replace)
90
+ unlink (tmppath.c_str ());
91
+ }
92
+
93
+ exit :
94
+ free (keyval);
95
+ return rc;
96
+ }
97
+
98
+
99
+ /* ****************************************************************************/
100
+
101
+ rpmRC keystore_fs::load_keys (rpmtxn txn, rpmKeyring keyring)
102
+ {
103
+ return load_keys_from_glob (txn, keyring, " %{_keyringpath}/*.key" );
104
+ }
105
+
58
106
rpmRC keystore_fs::delete_key (rpmtxn txn, const string & keyid, const string & newname)
59
107
{
60
108
rpmRC rc = RPMRC_NOTFOUND;
@@ -82,55 +130,113 @@ rpmRC keystore_fs::delete_key(rpmtxn txn, rpmPubkey key)
82
130
rpmRC keystore_fs::import_key (rpmtxn txn, rpmPubkey key, int replace, rpmFlags flags)
83
131
{
84
132
rpmRC rc = RPMRC_FAIL;
85
- const char *fp = rpmPubkeyFingerprintAsHex (key);
86
- char *keyfmt = rstrscat (NULL , " gpg-pubkey-" , fp, " .key" , NULL );
87
- char *keyval = rpmPubkeyArmorWrap (key);
88
- char *path = rpmGenPath (rpmtxnRootDir (txn), " %{_keyringpath}/" , keyfmt);
89
- char *tmppath = NULL ;
133
+ string fp = rpmPubkeyFingerprintAsHex (key);
134
+ string keyfmt = " gpg-pubkey-" + fp + " .key" ;
135
+ char *dir = rpmGenPath (rpmtxnRootDir (txn), " %{_keyringpath}/" , NULL );
136
+ string dirstr = dir;
90
137
91
- if (replace) {
92
- rasprintf (&tmppath, " %s.new" , path);
93
- unlink (tmppath);
138
+ rc = write_key_to_disk (key, dirstr, keyfmt, replace, flags);
139
+
140
+ if (!rc && replace) {
141
+ /* find and delete the old pubkey entry */
142
+ if (delete_key (txn, fp, keyfmt) == RPMRC_NOTFOUND) {
143
+ /* make sure an old, short keyid version gets removed */
144
+ delete_key (txn, fp.substr (32 ), keyfmt);
145
+ }
94
146
}
95
147
96
- if (rpmMkdirs (rpmtxnRootDir (txn), " %{_keyringpath}" )) {
148
+ free (dir);
149
+ return rc;
150
+ }
151
+
152
+ /* ****************************************************************************/
153
+
154
+ static rpmRC acquire_write_lock (rpmtxn txn)
155
+ {
156
+ char * keyringpath = rpmGenPath (rpmtxnRootDir (txn), " %{_keyringpath}/" , NULL );
157
+ char * lockpath = rpmGenPath (rpmtxnRootDir (txn), " %{_keyringpath}/" , " writelock" );
158
+ FILE* fp = NULL ;
159
+ rpmRC rc = RPMRC_FAIL;
160
+
161
+ if (rpmMkdirs (NULL , keyringpath)) {
97
162
rpmlog (RPMLOG_ERR, _ (" failed to create keyring directory %s: %s\n " ),
98
- path , strerror (errno));
163
+ keyringpath , strerror (errno));
99
164
goto exit ;
100
165
}
101
166
102
- if (FD_t fd = Fopen (tmppath ? tmppath : path, " wx" )) {
103
- size_t keylen = strlen (keyval);
104
- if (Fwrite (keyval, 1 , keylen, fd) == keylen)
105
- rc = RPMRC_OK;
106
- Fclose (fd);
107
- }
108
- if (!rc && tmppath && rename (tmppath, path) != 0 )
109
- rc = RPMRC_FAIL;
167
+ fp = std::fopen (lockpath, " wx" );
110
168
111
- if (rc ) {
112
- rpmlog (RPMLOG_ERR, _ (" failed to import key: %s: %s\n " ),
113
- tmppath ? tmppath : path, strerror (errno));
114
- if (tmppath)
115
- unlink (tmppath );
169
+ if (!fp ) {
170
+ rpmlog (RPMLOG_ERR, _ (" Can't acquire writelock for keyring at %s\n " ), keyringpath);
171
+ } else {
172
+ rc = RPMRC_OK;
173
+ std::fclose (fp );
116
174
}
117
175
118
- if (!rc && replace) {
119
- /* find and delete the old pubkey entry */
120
- if (delete_key (txn, fp, keyfmt) == RPMRC_NOTFOUND) {
121
- /* make sure an old, short keyid version gets removed */
122
- delete_key (txn, fp+32 , keyfmt);
123
- }
124
- }
176
+ exit :
177
+ free (keyringpath);
178
+ free (lockpath);
179
+ return rc;
180
+ }
125
181
126
- exit :
182
+ static void free_write_lock (rpmtxn txn)
183
+ {
184
+ char * path = rpmGenPath (rpmtxnRootDir (txn), " %{_keyringpath}/" , " writelock" );
185
+ unlink (path);
127
186
free (path);
128
- free (keyval);
129
- free (keyfmt);
130
- free (tmppath);
187
+ }
188
+
189
+ rpmRC keystore_openpgp_cert_d::load_keys (rpmtxn txn, rpmKeyring keyring)
190
+ {
191
+ return load_keys_from_glob (txn, keyring, " %{_keyringpath}/*/*" );
192
+ }
193
+
194
+ rpmRC keystore_openpgp_cert_d::delete_key (rpmtxn txn, rpmPubkey key)
195
+ {
196
+ rpmRC rc = RPMRC_NOTFOUND;
197
+
198
+ if (acquire_write_lock (txn) != RPMRC_OK)
199
+ return RPMRC_FAIL;
200
+
201
+ string fp = rpmPubkeyFingerprintAsHex (key);
202
+ string dir = fp.substr (0 , 2 );
203
+ string filename = fp.substr (2 );
204
+ char * filepath = rpmGetPath (rpmtxnRootDir (txn), " %{_keyringpath}/" , dir.c_str (), " /" , filename.c_str (), NULL );
205
+ char * dirpath = rpmGetPath (rpmtxnRootDir (txn), " %{_keyringpath}/" , dir.c_str (), NULL );
206
+
207
+ if (!access (filepath, F_OK))
208
+ rc = unlink (filepath) ? RPMRC_FAIL : RPMRC_OK;
209
+ /* unlink directory if empty */
210
+ unlink (dirpath);
211
+
212
+ free (filepath);
213
+ free (dirpath);
214
+ free_write_lock (txn);
131
215
return rc;
132
216
}
133
217
218
+ rpmRC keystore_openpgp_cert_d::import_key (rpmtxn txn, rpmPubkey key, int replace, rpmFlags flags)
219
+ {
220
+ rpmRC rc = RPMRC_NOTFOUND;
221
+
222
+ if ((rc = acquire_write_lock (txn)) == RPMRC_OK) {
223
+ string fp = rpmPubkeyFingerprintAsHex (key);
224
+ string dir = fp.substr (0 , 2 );
225
+ string filename = fp.substr (2 );
226
+ char *dirpath = rpmGetPath (rpmtxnRootDir (txn), " %{_keyringpath}/" , dir.c_str (), NULL );
227
+ string dirstr = dirpath;
228
+
229
+ rc = write_key_to_disk (key, dirstr, filename, replace, flags);
230
+
231
+ free_write_lock (txn);
232
+ free (dirpath);
233
+ }
234
+
235
+ return rc;
236
+ }
237
+
238
+ /* ****************************************************************************/
239
+
134
240
rpmRC keystore_rpmdb::load_keys (rpmtxn txn, rpmKeyring keyring)
135
241
{
136
242
Header h;
0 commit comments