Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34109798
keydb.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
19 KB
Subscribers
None
keydb.c
View Options
/* keydb.c - key database dispatcher
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
* 2008, 2009, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include
<config.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<errno.h>
#include
<assert.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<unistd.h>
#include
"gpg.h"
#include
"util.h"
#include
"options.h"
#include
"main.h"
/*try_make_homedir ()*/
#include
"packet.h"
#include
"keyring.h"
#include
"keydb.h"
#include
"i18n.h"
static
int
active_handles
;
typedef
enum
{
KEYDB_RESOURCE_TYPE_NONE
=
0
,
KEYDB_RESOURCE_TYPE_KEYRING
}
KeydbResourceType
;
#define MAX_KEYDB_RESOURCES 40
struct
resource_item
{
KeydbResourceType
type
;
union
{
KEYRING_HANDLE
kr
;
}
u
;
void
*
token
;
};
static
struct
resource_item
all_resources
[
MAX_KEYDB_RESOURCES
];
static
int
used_resources
;
static
void
*
primary_keyring
=
NULL
;
struct
keydb_handle
{
int
locked
;
int
found
;
int
current
;
int
used
;
/* Number of items in ACTIVE. */
struct
resource_item
active
[
MAX_KEYDB_RESOURCES
];
};
static
int
lock_all
(
KEYDB_HANDLE
hd
);
static
void
unlock_all
(
KEYDB_HANDLE
hd
);
/* Handle the creation of a keyring if it does not yet exist. Take
into acount that other processes might have the keyring already
locked. This lock check does not work if the directory itself is
not yet available. */
static
int
maybe_create_keyring
(
char
*
filename
,
int
force
)
{
dotlock_t
lockhd
=
NULL
;
IOBUF
iobuf
;
int
rc
;
mode_t
oldmask
;
char
*
last_slash_in_filename
;
int
save_slash
;
/* A quick test whether the filename already exists. */
if
(
!
access
(
filename
,
F_OK
))
return
0
;
/* If we don't want to create a new file at all, there is no need to
go any further - bail out right here. */
if
(
!
force
)
return
gpg_error
(
GPG_ERR_ENOENT
);
/* First of all we try to create the home directory. Note, that we
don't do any locking here because any sane application of gpg
would create the home directory by itself and not rely on gpg's
tricky auto-creation which is anyway only done for some home
directory name patterns. */
last_slash_in_filename
=
strrchr
(
filename
,
DIRSEP_C
);
#if HAVE_W32_SYSTEM
{
/* Windows may either have a slash or a backslash. Take care of it. */
char
*
p
=
strrchr
(
filename
,
'/'
);
if
(
!
last_slash_in_filename
||
p
>
last_slash_in_filename
)
last_slash_in_filename
=
p
;
}
#endif
/*HAVE_W32_SYSTEM*/
if
(
!
last_slash_in_filename
)
return
gpg_error
(
GPG_ERR_ENOENT
);
/* No slash at all - should
not happen though. */
save_slash
=
*
last_slash_in_filename
;
*
last_slash_in_filename
=
0
;
if
(
access
(
filename
,
F_OK
))
{
static
int
tried
;
if
(
!
tried
)
{
tried
=
1
;
try_make_homedir
(
filename
);
}
if
(
access
(
filename
,
F_OK
))
{
rc
=
gpg_error_from_syserror
();
*
last_slash_in_filename
=
save_slash
;
goto
leave
;
}
}
*
last_slash_in_filename
=
save_slash
;
/* To avoid races with other instances of gpg trying to create or
update the keyring (it is removed during an update for a short
time), we do the next stuff in a locked state. */
lockhd
=
dotlock_create
(
filename
,
0
);
if
(
!
lockhd
)
{
/* A reason for this to fail is that the directory is not
writable. However, this whole locking stuff does not make
sense if this is the case. An empty non-writable directory
with no keyring is not really useful at all. */
if
(
opt
.
verbose
)
log_info
(
"can't allocate lock for `%s'
\n
"
,
filename
);
if
(
!
force
)
return
gpg_error
(
GPG_ERR_ENOENT
);
else
return
gpg_error
(
GPG_ERR_GENERAL
);
}
if
(
dotlock_take
(
lockhd
,
-1
)
)
{
/* This is something bad. Probably a stale lockfile. */
log_info
(
"can't lock `%s'
\n
"
,
filename
);
rc
=
G10ERR_GENERAL
;
goto
leave
;
}
/* Now the real test while we are locked. */
if
(
!
access
(
filename
,
F_OK
))
{
rc
=
0
;
/* Okay, we may access the file now. */
goto
leave
;
}
/* The file does not yet exist, create it now. */
oldmask
=
umask
(
077
);
if
(
is_secured_filename
(
filename
))
{
iobuf
=
NULL
;
gpg_err_set_errno
(
EPERM
);
}
else
iobuf
=
iobuf_create
(
filename
);
umask
(
oldmask
);
if
(
!
iobuf
)
{
rc
=
gpg_error_from_syserror
();
log_error
(
_
(
"error creating keyring `%s': %s
\n
"
),
filename
,
strerror
(
errno
));
goto
leave
;
}
if
(
!
opt
.
quiet
)
log_info
(
_
(
"keyring `%s' created
\n
"
),
filename
);
iobuf_close
(
iobuf
);
/* Must invalidate that ugly cache */
iobuf_ioctl
(
NULL
,
IOBUF_IOCTL_INVALIDATE_CACHE
,
0
,
filename
);
rc
=
0
;
leave
:
if
(
lockhd
)
{
dotlock_release
(
lockhd
);
dotlock_destroy
(
lockhd
);
}
return
rc
;
}
/*
* Register a resource (which currently may only be a keyring file).
* The first keyring which is added by this function is
* created if it does not exist.
* Note: this function may be called before secure memory is
* available.
* Flag 1 - Force.
* Flag 2 - Mark resource as primary.
* Flag 4 - This is a default resources.
* Flag 8 - Open as read-only.
*/
gpg_error_t
keydb_add_resource
(
const
char
*
url
,
int
flags
)
{
static
int
any_public
;
const
char
*
resname
=
url
;
char
*
filename
=
NULL
;
int
force
=
(
flags
&
1
);
int
read_only
=
!!
(
flags
&
8
);
int
rc
=
0
;
KeydbResourceType
rt
=
KEYDB_RESOURCE_TYPE_NONE
;
void
*
token
;
if
(
read_only
)
force
=
0
;
/* Do we have an URL?
* gnupg-ring:filename := this is a plain keyring
* filename := See what is is, but create as plain keyring.
*/
if
(
strlen
(
resname
)
>
11
)
{
if
(
!
strncmp
(
resname
,
"gnupg-ring:"
,
11
)
)
{
rt
=
KEYDB_RESOURCE_TYPE_KEYRING
;
resname
+=
11
;
}
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
else
if
(
strchr
(
resname
,
':'
))
{
log_error
(
"invalid key resource URL `%s'
\n
"
,
url
);
rc
=
gpg_error
(
GPG_ERR_GENERAL
);
goto
leave
;
}
#endif
/* !HAVE_DRIVE_LETTERS && !__riscos__ */
}
if
(
*
resname
!=
DIRSEP_C
)
{
/* Do tilde expansion etc. */
if
(
strchr
(
resname
,
DIRSEP_C
)
)
filename
=
make_filename
(
resname
,
NULL
);
else
filename
=
make_filename
(
opt
.
homedir
,
resname
,
NULL
);
}
else
filename
=
xstrdup
(
resname
);
if
(
!
force
&&
!
read_only
)
force
=
!
any_public
;
/* See whether we can determine the filetype. */
if
(
rt
==
KEYDB_RESOURCE_TYPE_NONE
)
{
FILE
*
fp
=
fopen
(
filename
,
"rb"
);
if
(
fp
)
{
u32
magic
;
if
(
fread
(
&
magic
,
4
,
1
,
fp
)
==
1
)
{
if
(
magic
==
0x13579ace
||
magic
==
0xce9a5713
)
;
/* GDBM magic - not anymore supported. */
else
rt
=
KEYDB_RESOURCE_TYPE_KEYRING
;
}
else
/* Maybe empty: assume keyring. */
rt
=
KEYDB_RESOURCE_TYPE_KEYRING
;
fclose
(
fp
);
}
else
/* No file yet: create keyring. */
rt
=
KEYDB_RESOURCE_TYPE_KEYRING
;
}
switch
(
rt
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
log_error
(
"unknown type of key resource `%s'
\n
"
,
url
);
rc
=
gpg_error
(
GPG_ERR_GENERAL
);
goto
leave
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
rc
=
maybe_create_keyring
(
filename
,
force
);
if
(
rc
)
goto
leave
;
if
(
keyring_register_filename
(
filename
,
read_only
,
&
token
))
{
if
(
used_resources
>=
MAX_KEYDB_RESOURCES
)
rc
=
gpg_error
(
GPG_ERR_RESOURCE_LIMIT
);
else
{
if
(
flags
&
2
)
primary_keyring
=
token
;
all_resources
[
used_resources
].
type
=
rt
;
all_resources
[
used_resources
].
u
.
kr
=
NULL
;
/* Not used here */
all_resources
[
used_resources
].
token
=
token
;
used_resources
++
;
}
}
else
{
/* This keyring was already registered, so ignore it.
However, we can still mark it as primary even if it was
already registered. */
if
(
flags
&
2
)
primary_keyring
=
token
;
}
break
;
default
:
log_error
(
"resource type of `%s' not supported
\n
"
,
url
);
rc
=
gpg_error
(
GPG_ERR_GENERAL
);
goto
leave
;
}
/* fixme: check directory permissions and print a warning */
leave
:
if
(
rc
)
log_error
(
_
(
"keyblock resource `%s': %s
\n
"
),
filename
,
gpg_strerror
(
rc
));
else
any_public
=
1
;
xfree
(
filename
);
return
rc
;
}
KEYDB_HANDLE
keydb_new
(
void
)
{
KEYDB_HANDLE
hd
;
int
i
,
j
;
hd
=
xmalloc_clear
(
sizeof
*
hd
);
hd
->
found
=
-1
;
assert
(
used_resources
<=
MAX_KEYDB_RESOURCES
);
for
(
i
=
j
=
0
;
i
<
used_resources
;
i
++
)
{
switch
(
all_resources
[
i
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
/* ignore */
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
hd
->
active
[
j
].
type
=
all_resources
[
i
].
type
;
hd
->
active
[
j
].
token
=
all_resources
[
i
].
token
;
hd
->
active
[
j
].
u
.
kr
=
keyring_new
(
all_resources
[
i
].
token
);
if
(
!
hd
->
active
[
j
].
u
.
kr
)
{
xfree
(
hd
);
return
NULL
;
/* fixme: release all previously allocated handles*/
}
j
++
;
break
;
}
}
hd
->
used
=
j
;
active_handles
++
;
return
hd
;
}
void
keydb_release
(
KEYDB_HANDLE
hd
)
{
int
i
;
if
(
!
hd
)
return
;
assert
(
active_handles
>
0
);
active_handles
--
;
unlock_all
(
hd
);
for
(
i
=
0
;
i
<
hd
->
used
;
i
++
)
{
switch
(
hd
->
active
[
i
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
keyring_release
(
hd
->
active
[
i
].
u
.
kr
);
break
;
}
}
xfree
(
hd
);
}
/*
* Return the name of the current resource. This is function first
* looks for the last found found, then for the current search
* position, and last returns the first available resource. The
* returned string is only valid as long as the handle exists. This
* function does only return NULL if no handle is specified, in all
* other error cases an empty string is returned.
*/
const
char
*
keydb_get_resource_name
(
KEYDB_HANDLE
hd
)
{
int
idx
;
const
char
*
s
=
NULL
;
if
(
!
hd
)
return
NULL
;
if
(
hd
->
found
>=
0
&&
hd
->
found
<
hd
->
used
)
idx
=
hd
->
found
;
else
if
(
hd
->
current
>=
0
&&
hd
->
current
<
hd
->
used
)
idx
=
hd
->
current
;
else
idx
=
0
;
switch
(
hd
->
active
[
idx
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
s
=
NULL
;
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
s
=
keyring_get_resource_name
(
hd
->
active
[
idx
].
u
.
kr
);
break
;
}
return
s
?
s
:
""
;
}
static
int
lock_all
(
KEYDB_HANDLE
hd
)
{
int
i
,
rc
=
0
;
for
(
i
=
0
;
!
rc
&&
i
<
hd
->
used
;
i
++
)
{
switch
(
hd
->
active
[
i
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
rc
=
keyring_lock
(
hd
->
active
[
i
].
u
.
kr
,
1
);
break
;
}
}
if
(
rc
)
{
/* Revert the already set locks. */
for
(
i
--
;
i
>=
0
;
i
--
)
{
switch
(
hd
->
active
[
i
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
keyring_lock
(
hd
->
active
[
i
].
u
.
kr
,
0
);
break
;
}
}
}
else
hd
->
locked
=
1
;
return
rc
;
}
static
void
unlock_all
(
KEYDB_HANDLE
hd
)
{
int
i
;
if
(
!
hd
->
locked
)
return
;
for
(
i
=
hd
->
used
-1
;
i
>=
0
;
i
--
)
{
switch
(
hd
->
active
[
i
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
keyring_lock
(
hd
->
active
[
i
].
u
.
kr
,
0
);
break
;
}
}
hd
->
locked
=
0
;
}
/*
* Return the last found keyring. Caller must free it.
* The returned keyblock has the kbode flag bit 0 set for the node with
* the public key used to locate the keyblock or flag bit 1 set for
* the user ID node.
*/
gpg_error_t
keydb_get_keyblock
(
KEYDB_HANDLE
hd
,
KBNODE
*
ret_kb
)
{
gpg_error_t
err
=
0
;
if
(
!
hd
)
return
gpg_error
(
GPG_ERR_INV_ARG
);
if
(
hd
->
found
<
0
||
hd
->
found
>=
hd
->
used
)
return
gpg_error
(
GPG_ERR_VALUE_NOT_FOUND
);
switch
(
hd
->
active
[
hd
->
found
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
err
=
gpg_error
(
GPG_ERR_GENERAL
);
/* oops */
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
err
=
keyring_get_keyblock
(
hd
->
active
[
hd
->
found
].
u
.
kr
,
ret_kb
);
break
;
}
return
err
;
}
/*
* Update the current keyblock with the keyblock KB
*/
gpg_error_t
keydb_update_keyblock
(
KEYDB_HANDLE
hd
,
kbnode_t
kb
)
{
gpg_error_t
rc
;
if
(
!
hd
)
return
gpg_error
(
GPG_ERR_INV_ARG
);
if
(
hd
->
found
<
0
||
hd
->
found
>=
hd
->
used
)
return
gpg_error
(
GPG_ERR_VALUE_NOT_FOUND
);
if
(
opt
.
dry_run
)
return
0
;
rc
=
lock_all
(
hd
);
if
(
rc
)
return
rc
;
switch
(
hd
->
active
[
hd
->
found
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
rc
=
gpg_error
(
GPG_ERR_GENERAL
);
/* oops */
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
rc
=
keyring_update_keyblock
(
hd
->
active
[
hd
->
found
].
u
.
kr
,
kb
);
break
;
}
unlock_all
(
hd
);
return
rc
;
}
/*
* Insert a new KB into one of the resources.
*/
gpg_error_t
keydb_insert_keyblock
(
KEYDB_HANDLE
hd
,
kbnode_t
kb
)
{
int
rc
;
int
idx
;
if
(
!
hd
)
return
gpg_error
(
GPG_ERR_INV_ARG
);
if
(
opt
.
dry_run
)
return
0
;
if
(
hd
->
found
>=
0
&&
hd
->
found
<
hd
->
used
)
idx
=
hd
->
found
;
else
if
(
hd
->
current
>=
0
&&
hd
->
current
<
hd
->
used
)
idx
=
hd
->
current
;
else
return
gpg_error
(
GPG_ERR_GENERAL
);
rc
=
lock_all
(
hd
);
if
(
rc
)
return
rc
;
switch
(
hd
->
active
[
idx
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
rc
=
gpg_error
(
GPG_ERR_GENERAL
);
/* oops */
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
rc
=
keyring_insert_keyblock
(
hd
->
active
[
idx
].
u
.
kr
,
kb
);
break
;
}
unlock_all
(
hd
);
return
rc
;
}
/*
* Delete the current keyblock.
*/
gpg_error_t
keydb_delete_keyblock
(
KEYDB_HANDLE
hd
)
{
gpg_error_t
rc
;
if
(
!
hd
)
return
gpg_error
(
GPG_ERR_INV_ARG
);
if
(
hd
->
found
<
0
||
hd
->
found
>=
hd
->
used
)
return
gpg_error
(
GPG_ERR_VALUE_NOT_FOUND
);
if
(
opt
.
dry_run
)
return
0
;
rc
=
lock_all
(
hd
);
if
(
rc
)
return
rc
;
switch
(
hd
->
active
[
hd
->
found
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
rc
=
gpg_error
(
GPG_ERR_GENERAL
);
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
rc
=
keyring_delete_keyblock
(
hd
->
active
[
hd
->
found
].
u
.
kr
);
break
;
}
unlock_all
(
hd
);
return
rc
;
}
/*
* Locate the default writable key resource, so that the next
* operation (which is only relevant for inserts) will be done on this
* resource.
*/
gpg_error_t
keydb_locate_writable
(
KEYDB_HANDLE
hd
,
const
char
*
reserved
)
{
gpg_error_t
rc
;
(
void
)
reserved
;
if
(
!
hd
)
return
G10ERR_INV_ARG
;
rc
=
keydb_search_reset
(
hd
);
/* this does reset hd->current */
if
(
rc
)
return
rc
;
/* If we have a primary set, try that one first */
if
(
primary_keyring
)
{
for
(
;
hd
->
current
>=
0
&&
hd
->
current
<
hd
->
used
;
hd
->
current
++
)
{
if
(
hd
->
active
[
hd
->
current
].
token
==
primary_keyring
)
{
if
(
keyring_is_writable
(
hd
->
active
[
hd
->
current
].
token
))
return
0
;
else
break
;
}
}
rc
=
keydb_search_reset
(
hd
);
/* this does reset hd->current */
if
(
rc
)
return
rc
;
}
for
(
;
hd
->
current
>=
0
&&
hd
->
current
<
hd
->
used
;
hd
->
current
++
)
{
switch
(
hd
->
active
[
hd
->
current
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
BUG
();
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
if
(
keyring_is_writable
(
hd
->
active
[
hd
->
current
].
token
))
return
0
;
/* found (hd->current is set to it) */
break
;
}
}
return
gpg_error
(
GPG_ERR_NOT_FOUND
);
}
/*
* Rebuild the caches of all key resources.
*/
void
keydb_rebuild_caches
(
int
noisy
)
{
int
i
,
rc
;
for
(
i
=
0
;
i
<
used_resources
;
i
++
)
{
if
(
!
keyring_is_writable
(
all_resources
[
i
].
token
))
continue
;
switch
(
all_resources
[
i
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
/* ignore */
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
rc
=
keyring_rebuild_cache
(
all_resources
[
i
].
token
,
noisy
);
if
(
rc
)
log_error
(
_
(
"failed to rebuild keyring cache: %s
\n
"
),
g10_errstr
(
rc
));
break
;
}
}
}
/*
* Start the next search on this handle right at the beginning
*/
gpg_error_t
keydb_search_reset
(
KEYDB_HANDLE
hd
)
{
gpg_error_t
rc
=
0
;
int
i
;
if
(
!
hd
)
return
gpg_error
(
GPG_ERR_INV_ARG
);
hd
->
current
=
0
;
hd
->
found
=
-1
;
/* Now reset all resources. */
for
(
i
=
0
;
!
rc
&&
i
<
hd
->
used
;
i
++
)
{
switch
(
hd
->
active
[
i
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
rc
=
keyring_search_reset
(
hd
->
active
[
i
].
u
.
kr
);
break
;
}
}
return
rc
;
}
/*
* Search through all keydb resources, starting at the current
* position, for a keyblock which contains one of the keys described
* in the DESC array. Returns GPG_ERR_NOT_FOUND if no matching
* keyring was found.
*/
gpg_error_t
keydb_search2
(
KEYDB_HANDLE
hd
,
KEYDB_SEARCH_DESC
*
desc
,
size_t
ndesc
,
size_t
*
descindex
)
{
gpg_error_t
rc
;
if
(
!
hd
)
return
gpg_error
(
GPG_ERR_INV_ARG
);
rc
=
-1
;
while
((
rc
==
-1
||
gpg_err_code
(
rc
)
==
GPG_ERR_EOF
)
&&
hd
->
current
>=
0
&&
hd
->
current
<
hd
->
used
)
{
switch
(
hd
->
active
[
hd
->
current
].
type
)
{
case
KEYDB_RESOURCE_TYPE_NONE
:
BUG
();
/* we should never see it here */
break
;
case
KEYDB_RESOURCE_TYPE_KEYRING
:
rc
=
keyring_search
(
hd
->
active
[
hd
->
current
].
u
.
kr
,
desc
,
ndesc
,
descindex
);
break
;
}
if
(
rc
==
-1
||
gpg_err_code
(
rc
)
==
GPG_ERR_EOF
)
{
/* EOF -> switch to next resource */
hd
->
current
++
;
}
else
if
(
!
rc
)
hd
->
found
=
hd
->
current
;
}
return
((
rc
==
-1
||
gpg_err_code
(
rc
)
==
GPG_ERR_EOF
)
?
gpg_error
(
GPG_ERR_NOT_FOUND
)
:
rc
);
}
gpg_error_t
keydb_search_first
(
KEYDB_HANDLE
hd
)
{
KEYDB_SEARCH_DESC
desc
;
memset
(
&
desc
,
0
,
sizeof
desc
);
desc
.
mode
=
KEYDB_SEARCH_MODE_FIRST
;
return
keydb_search
(
hd
,
&
desc
,
1
);
}
gpg_error_t
keydb_search_next
(
KEYDB_HANDLE
hd
)
{
KEYDB_SEARCH_DESC
desc
;
memset
(
&
desc
,
0
,
sizeof
desc
);
desc
.
mode
=
KEYDB_SEARCH_MODE_NEXT
;
return
keydb_search
(
hd
,
&
desc
,
1
);
}
gpg_error_t
keydb_search_kid
(
KEYDB_HANDLE
hd
,
u32
*
kid
)
{
KEYDB_SEARCH_DESC
desc
;
memset
(
&
desc
,
0
,
sizeof
desc
);
desc
.
mode
=
KEYDB_SEARCH_MODE_LONG_KID
;
desc
.
u
.
kid
[
0
]
=
kid
[
0
];
desc
.
u
.
kid
[
1
]
=
kid
[
1
];
return
keydb_search
(
hd
,
&
desc
,
1
);
}
gpg_error_t
keydb_search_fpr
(
KEYDB_HANDLE
hd
,
const
byte
*
fpr
)
{
KEYDB_SEARCH_DESC
desc
;
memset
(
&
desc
,
0
,
sizeof
desc
);
desc
.
mode
=
KEYDB_SEARCH_MODE_FPR
;
memcpy
(
desc
.
u
.
fpr
,
fpr
,
MAX_FINGERPRINT_LEN
);
return
keydb_search
(
hd
,
&
desc
,
1
);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Dec 5, 4:59 AM (1 h, 5 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ba/c9/0121bca09851f6342d6ada47c486
Attached To
rG GnuPG
Event Timeline
Log In to Comment