Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34109722
assuan.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
5 KB
Subscribers
None
assuan.cpp
View Options
/*
utils/assuan.cpp
This file is part of libkleopatra
SPDX-FileCopyrightText: 2021, 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
<config-libkleo.h>
#include
"assuan.h"
#include
<libkleo_debug.h>
#if __has_include(<QGpgME/Debug>)
#include
<QGpgME/Debug>
#endif
#include
<QThread>
#include
<gpgme++/context.h>
#include
<gpgme++/defaultassuantransaction.h>
#include
<gpgme++/error.h>
using
namespace
GpgME
;
using
namespace
Kleo
;
using
namespace
Kleo
::
Assuan
;
using
namespace
std
::
chrono_literals
;
static
const
auto
initialRetryDelay
=
125
ms
;
static
const
auto
maxRetryDelay
=
1000
ms
;
static
const
auto
maxConnectionAttempts
=
10
;
namespace
{
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
static
QDebug
operator
<<
(
QDebug
s
,
const
std
::
string
&
string
)
{
return
s
<<
QString
::
fromStdString
(
string
);
}
#endif
static
QDebug
operator
<<
(
QDebug
s
,
const
std
::
vector
<
std
::
pair
<
std
::
string
,
std
::
string
>>
&
v
)
{
using
pair
=
std
::
pair
<
std
::
string
,
std
::
string
>
;
s
<<
'('
;
for
(
const
pair
&
p
:
v
)
{
s
<<
"status("
<<
QString
::
fromStdString
(
p
.
first
)
<<
") ="
<<
QString
::
fromStdString
(
p
.
second
)
<<
'\n'
;
}
return
s
<<
')'
;
}
}
bool
Kleo
::
Assuan
::
agentIsRunning
()
{
Error
err
;
const
std
::
unique_ptr
<
Context
>
ctx
=
Context
::
createForEngine
(
AssuanEngine
,
&
err
);
if
(
err
)
{
qCWarning
(
LIBKLEO_LOG
)
<<
__func__
<<
": Creating context for Assuan engine failed:"
<<
err
;
return
false
;
}
static
const
char
*
command
=
"GETINFO version"
;
err
=
ctx
->
assuanTransact
(
command
);
if
(
!
err
)
{
// all good
}
else
if
(
err
.
code
()
==
GPG_ERR_ASS_CONNECT_FAILED
)
{
qCDebug
(
LIBKLEO_LOG
)
<<
__func__
<<
": Connecting to the agent failed."
;
}
else
{
qCWarning
(
LIBKLEO_LOG
)
<<
__func__
<<
": Starting Assuan transaction for"
<<
command
<<
"failed:"
<<
err
;
}
return
!
err
;
}
std
::
unique_ptr
<
GpgME
::
AssuanTransaction
>
Kleo
::
Assuan
::
sendCommand
(
std
::
shared_ptr
<
GpgME
::
Context
>
&
context
,
const
std
::
string
&
command
,
std
::
unique_ptr
<
GpgME
::
AssuanTransaction
>
transaction
,
GpgME
::
Error
&
err
)
{
qCDebug
(
LIBKLEO_LOG
)
<<
__func__
<<
command
;
int
connectionAttempts
=
1
;
err
=
context
->
assuanTransact
(
command
.
c_str
(),
std
::
move
(
transaction
));
auto
retryDelay
=
initialRetryDelay
;
while
(
err
.
code
()
==
GPG_ERR_ASS_CONNECT_FAILED
&&
connectionAttempts
<
maxConnectionAttempts
)
{
// Esp. on Windows the agent processes may take their time so we try
// in increasing waits for them to start up
qCDebug
(
LIBKLEO_LOG
)
<<
"Connecting to the agent failed. Retrying in"
<<
retryDelay
.
count
()
<<
"ms"
;
QThread
::
msleep
(
retryDelay
.
count
());
retryDelay
=
std
::
min
(
retryDelay
*
2
,
maxRetryDelay
);
connectionAttempts
++
;
err
=
context
->
assuanTransact
(
command
.
c_str
(),
context
->
takeLastAssuanTransaction
());
}
if
(
err
.
code
())
{
qCDebug
(
LIBKLEO_LOG
)
<<
__func__
<<
command
<<
"failed:"
<<
err
;
if
(
err
.
code
()
>=
GPG_ERR_ASS_GENERAL
&&
err
.
code
()
<=
GPG_ERR_ASS_UNKNOWN_INQUIRE
)
{
qCDebug
(
LIBKLEO_LOG
)
<<
"Assuan problem, killing context"
;
context
.
reset
();
}
return
{};
}
return
context
->
takeLastAssuanTransaction
();
}
std
::
unique_ptr
<
DefaultAssuanTransaction
>
Kleo
::
Assuan
::
sendCommand
(
std
::
shared_ptr
<
Context
>
&
context
,
const
std
::
string
&
command
,
Error
&
err
)
{
std
::
unique_ptr
<
AssuanTransaction
>
t
=
sendCommand
(
context
,
command
,
std
::
make_unique
<
DefaultAssuanTransaction
>
(),
err
);
return
std
::
unique_ptr
<
DefaultAssuanTransaction
>
(
dynamic_cast
<
DefaultAssuanTransaction
*>
(
t
.
release
()));
}
std
::
string
Kleo
::
Assuan
::
sendDataCommand
(
std
::
shared_ptr
<
Context
>
context
,
const
std
::
string
&
command
,
Error
&
err
)
{
std
::
string
data
;
const
std
::
unique_ptr
<
DefaultAssuanTransaction
>
t
=
sendCommand
(
context
,
command
,
err
);
if
(
t
.
get
())
{
data
=
t
->
data
();
qCDebug
(
LIBKLEO_LOG
)
<<
__func__
<<
command
<<
": got"
<<
QString
::
fromStdString
(
data
);
}
else
{
qCDebug
(
LIBKLEO_LOG
)
<<
__func__
<<
command
<<
": t == NULL"
;
}
return
data
;
}
std
::
vector
<
std
::
pair
<
std
::
string
,
std
::
string
>>
Kleo
::
Assuan
::
sendStatusLinesCommand
(
std
::
shared_ptr
<
Context
>
context
,
const
std
::
string
&
command
,
Error
&
err
)
{
std
::
vector
<
std
::
pair
<
std
::
string
,
std
::
string
>>
statusLines
;
const
std
::
unique_ptr
<
DefaultAssuanTransaction
>
t
=
sendCommand
(
context
,
command
,
err
);
if
(
t
.
get
())
{
statusLines
=
t
->
statusLines
();
qCDebug
(
LIBKLEO_LOG
)
<<
__func__
<<
command
<<
": got"
<<
statusLines
;
}
else
{
qCDebug
(
LIBKLEO_LOG
)
<<
__func__
<<
command
<<
": t == NULL"
;
}
return
statusLines
;
}
std
::
string
Kleo
::
Assuan
::
sendStatusCommand
(
const
std
::
shared_ptr
<
Context
>
&
context
,
const
std
::
string
&
command
,
Error
&
err
)
{
const
auto
lines
=
sendStatusLinesCommand
(
context
,
command
,
err
);
// The status is only the last attribute
// e.g. for SCD SERIALNO it would only be "SERIALNO" and for SCD GETATTR FOO
// it would only be FOO
const
auto
lastSpace
=
command
.
rfind
(
' '
);
const
auto
needle
=
lastSpace
==
std
::
string
::
npos
?
command
:
command
.
substr
(
lastSpace
+
1
);
for
(
const
auto
&
pair
:
lines
)
{
if
(
pair
.
first
==
needle
)
{
return
pair
.
second
;
}
}
return
{};
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Dec 5, 4:41 AM (1 d, 1 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
13/49/d3fd63049062ab785be9b10228c7
Attached To
rLIBKLEO Libkleo
Event Timeline
Log In to Comment