Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18824803
gpgmeedit.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
27 KB
Subscribers
None
gpgmeedit.c
View Options
/* gpgmetools.c - The GNU Privacy Assistant
* Copyright (C) 2002, Miguel Coca.
*
* This file is part of GPA
*
* GPA 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 2 of the License, or
* (at your option) any later version.
*
* GPA 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include
<config.h>
#include
"gpgmeedit.h"
#include
"passwddlg.h"
#include
<unistd.h>
/* The edit callback for all the edit operations is edit_fnc(). Each
* operation is modelled as a sequential machine (a Moore machine, to be
* precise). Therefore, for each operation you must write two functions.
*
* One of them is "action" or output function, that chooses the right value
* for *result (the next command issued in the edit command line) based on
* the current state. The other is the "transit" function, which chooses
* the next state based on the current state and the input (status code and
* args).
*
* See the comments below for details.
*/
/* Define this macro to 1 to enable debugging of the FSM. */
#define DEBUG_FSM 0
/* Prototype of the action function. Returns the error if there is one */
typedef
gpg_error_t
(
*
EditAction
)
(
int
state
,
void
*
opaque
,
char
**
result
);
/* Prototype of the transit function. Returns the next state. If and error
* is found changes *err. If there is no error it should NOT touch it */
typedef
int
(
*
EditTransit
)
(
int
current_state
,
gpgme_status_code_t
status
,
const
char
*
args
,
void
*
opaque
,
gpg_error_t
*
err
);
/* Data to be passed to the edit callback. Must be filled by the caller of
* gpgme_op_edit() */
struct
edit_parms_s
{
/* Current state */
int
state
;
/* Last error: The return code of gpgme_op_edit() is the return value of
* the last invocation of the callback. But returning an error from the
* callback does not abort the edit operation, so we must remember any
* error. In other words, errors from action() or transit() are sticky.
*/
gpg_error_t
err
;
/* The action function */
EditAction
action
;
/* The transit function */
EditTransit
transit
;
/* The output data object */
gpgme_data_t
out
;
/* Signal attachment id */
gulong
signal_id
;
/* Data to be passed to the previous functions */
void
*
opaque
;
/* The passwd dialog needs to see GPGME_STATUS_NEED_PASSPHRASE_SYM.
To make thinks easier it is only passed to the FSM if this flag
has been set. */
int
need_status_passphrase_sym
;
};
/* The edit callback proper */
static
gpg_error_t
edit_fnc
(
void
*
opaque
,
gpgme_status_code_t
status
,
const
char
*
args
,
int
fd
)
{
struct
edit_parms_s
*
parms
=
opaque
;
char
*
result
=
NULL
;
/* Ignore these status lines, as they don't require any response */
if
(
status
==
GPGME_STATUS_EOF
||
status
==
GPGME_STATUS_GOT_IT
||
status
==
GPGME_STATUS_NEED_PASSPHRASE
||
status
==
GPGME_STATUS_NEED_PASSPHRASE_SYM
||
status
==
GPGME_STATUS_GOOD_PASSPHRASE
||
status
==
GPGME_STATUS_BAD_PASSPHRASE
||
status
==
GPGME_STATUS_USERID_HINT
||
status
==
GPGME_STATUS_SIGEXPIRED
||
status
==
GPGME_STATUS_KEYEXPIRED
)
{
return
parms
->
err
;
}
else
if
(
!
parms
->
need_status_passphrase_sym
&&
status
==
GPGME_STATUS_NEED_PASSPHRASE_SYM
)
{
return
parms
->
err
;
}
#if DEBUG_FSM
g_debug
(
"edit_fnc: state=%d input=%d (%s)"
,
parms
->
state
,
status
,
args
);
#endif
/* Choose the next state based on the current one and the input */
parms
->
state
=
parms
->
transit
(
parms
->
state
,
status
,
args
,
parms
->
opaque
,
&
parms
->
err
);
if
(
gpg_err_code
(
parms
->
err
)
==
GPG_ERR_NO_ERROR
)
{
gpg_error_t
err
;
/* Choose the action based on the state */
err
=
parms
->
action
(
parms
->
state
,
parms
->
opaque
,
&
result
);
#if DEBUG_FSM
g_debug
(
"edit_fnc: newstate=%d err=%s result=%s"
,
parms
->
state
,
gpg_strerror
(
err
),
result
);
#endif
if
(
gpg_err_code
(
err
)
!=
GPG_ERR_NO_ERROR
)
{
parms
->
err
=
err
;
}
/* Send the command, if any was provided */
if
(
result
)
{
if
(
*
result
)
write
(
fd
,
result
,
strlen
(
result
));
write
(
fd
,
"
\n
"
,
1
);
}
}
else
{
#if DEBUG_FSM
g_debug
(
"edit_fnc: newstate=%d err=%s transit failed"
,
parms
->
state
,
gpg_strerror
(
parms
->
err
));
#endif
}
return
parms
->
err
;
}
/* Change expiry time */
typedef
enum
{
EXPIRE_START
,
EXPIRE_COMMAND
,
EXPIRE_DATE
,
EXPIRE_QUIT
,
EXPIRE_SAVE
,
EXPIRE_ERROR
}
ExpireState
;
static
gpg_error_t
edit_expire_fnc_action
(
int
state
,
void
*
opaque
,
char
**
result
)
{
gchar
*
date
=
opaque
;
switch
(
state
)
{
/* Start the operation */
case
EXPIRE_COMMAND
:
*
result
=
"expire"
;
break
;
/* Send the new expire date */
case
EXPIRE_DATE
:
*
result
=
date
;
break
;
/* End the operation */
case
EXPIRE_QUIT
:
*
result
=
"quit"
;
break
;
/* Save */
case
EXPIRE_SAVE
:
*
result
=
"Y"
;
break
;
/* Special state: an error ocurred. Do nothing until we can quit */
case
EXPIRE_ERROR
:
break
;
/* Can't happen */
default
:
return
gpg_error
(
GPG_ERR_GENERAL
);
}
return
gpg_error
(
GPG_ERR_NO_ERROR
);
}
static
int
edit_expire_fnc_transit
(
int
current_state
,
gpgme_status_code_t
status
,
const
char
*
args
,
void
*
opaque
,
gpg_error_t
*
err
)
{
int
next_state
;
switch
(
current_state
)
{
case
EXPIRE_START
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
EXPIRE_COMMAND
;
}
else
{
next_state
=
EXPIRE_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
EXPIRE_COMMAND
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keygen.valid"
))
{
next_state
=
EXPIRE_DATE
;
}
else
{
next_state
=
EXPIRE_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
EXPIRE_DATE
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
EXPIRE_QUIT
;
}
else
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keygen.valid"
))
{
next_state
=
EXPIRE_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_INV_TIME
);
}
else
{
next_state
=
EXPIRE_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
EXPIRE_QUIT
:
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"keyedit.save.okay"
))
{
next_state
=
EXPIRE_SAVE
;
}
else
{
next_state
=
EXPIRE_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
EXPIRE_ERROR
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
/* Go to quit operation state */
next_state
=
EXPIRE_QUIT
;
}
else
{
next_state
=
EXPIRE_ERROR
;
}
break
;
default
:
next_state
=
EXPIRE_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
return
next_state
;
}
/* Change the key ownertrust */
typedef
enum
{
TRUST_START
,
TRUST_COMMAND
,
TRUST_VALUE
,
TRUST_REALLY_ULTIMATE
,
TRUST_QUIT
,
TRUST_SAVE
,
TRUST_ERROR
}
TrustState
;
static
gpg_error_t
edit_trust_fnc_action
(
int
state
,
void
*
opaque
,
char
**
result
)
{
gchar
*
trust
=
opaque
;
switch
(
state
)
{
/* Start the operation */
case
TRUST_COMMAND
:
*
result
=
"trust"
;
break
;
/* Send the new trust date */
case
TRUST_VALUE
:
*
result
=
trust
;
break
;
/* Really set to ultimate trust */
case
TRUST_REALLY_ULTIMATE
:
*
result
=
"Y"
;
break
;
/* End the operation */
case
TRUST_QUIT
:
*
result
=
"quit"
;
break
;
/* Save */
case
TRUST_SAVE
:
*
result
=
"Y"
;
break
;
/* Special state: an error ocurred. Do nothing until we can quit */
case
TRUST_ERROR
:
break
;
/* Can't happen */
default
:
return
gpg_error
(
GPG_ERR_GENERAL
);
}
return
gpg_error
(
GPG_ERR_NO_ERROR
);
}
static
int
edit_trust_fnc_transit
(
int
current_state
,
gpgme_status_code_t
status
,
const
char
*
args
,
void
*
opaque
,
gpg_error_t
*
err
)
{
int
next_state
;
switch
(
current_state
)
{
case
TRUST_START
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
TRUST_COMMAND
;
}
else
{
next_state
=
TRUST_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
TRUST_COMMAND
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"edit_ownertrust.value"
))
{
next_state
=
TRUST_VALUE
;
}
else
{
next_state
=
TRUST_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
TRUST_VALUE
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
TRUST_QUIT
;
}
else
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"edit_ownertrust.set_ultimate.okay"
))
{
next_state
=
TRUST_REALLY_ULTIMATE
;
}
else
{
next_state
=
TRUST_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
TRUST_REALLY_ULTIMATE
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
TRUST_QUIT
;
}
else
{
next_state
=
TRUST_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
TRUST_QUIT
:
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"keyedit.save.okay"
))
{
next_state
=
TRUST_SAVE
;
}
else
{
next_state
=
TRUST_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
TRUST_ERROR
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
/* Go to quit operation state */
next_state
=
TRUST_QUIT
;
}
else
{
next_state
=
TRUST_ERROR
;
}
break
;
default
:
next_state
=
TRUST_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
return
next_state
;
}
/* Sign a key */
typedef
enum
{
SIGN_START
,
SIGN_COMMAND
,
SIGN_UIDS
,
SIGN_SET_EXPIRE
,
SIGN_SET_CHECK_LEVEL
,
SIGN_CONFIRM
,
SIGN_QUIT
,
SIGN_SAVE
,
SIGN_ERROR
}
SignState
;
struct
sign_parms_s
{
gchar
*
check_level
;
gboolean
local
;
};
static
gpg_error_t
edit_sign_fnc_action
(
int
state
,
void
*
opaque
,
char
**
result
)
{
struct
sign_parms_s
*
parms
=
opaque
;
switch
(
state
)
{
/* Start the operation */
case
SIGN_COMMAND
:
*
result
=
parms
->
local
?
"lsign"
:
"sign"
;
break
;
/* Sign all user ID's */
case
SIGN_UIDS
:
*
result
=
"Y"
;
break
;
/* The signature expires at the same time as the key */
case
SIGN_SET_EXPIRE
:
*
result
=
"Y"
;
break
;
/* Set the check level on the key */
case
SIGN_SET_CHECK_LEVEL
:
*
result
=
parms
->
check_level
;
break
;
/* Confirm the signature */
case
SIGN_CONFIRM
:
*
result
=
"Y"
;
break
;
/* End the operation */
case
SIGN_QUIT
:
*
result
=
"quit"
;
break
;
/* Save */
case
SIGN_SAVE
:
*
result
=
"Y"
;
break
;
/* Special state: an error ocurred. Do nothing until we can quit */
case
SIGN_ERROR
:
break
;
/* Can't happen */
default
:
return
gpg_error
(
GPG_ERR_GENERAL
);
}
return
gpg_error
(
GPG_ERR_NO_ERROR
);
}
static
int
edit_sign_fnc_transit
(
int
current_state
,
gpgme_status_code_t
status
,
const
char
*
args
,
void
*
opaque
,
gpg_error_t
*
err
)
{
int
next_state
;
switch
(
current_state
)
{
case
SIGN_START
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
SIGN_COMMAND
;
}
else
{
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
SIGN_COMMAND
:
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"keyedit.sign_all.okay"
))
{
next_state
=
SIGN_UIDS
;
}
else
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"sign_uid.okay"
))
{
next_state
=
SIGN_CONFIRM
;
}
else
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"sign_uid.expire"
))
{
next_state
=
SIGN_SET_EXPIRE
;
break
;
}
else
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"sign_uid.class"
))
{
next_state
=
SIGN_SET_CHECK_LEVEL
;
}
else
if
(
status
==
GPGME_STATUS_ALREADY_SIGNED
)
{
/* The key has already been signed with this key */
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_CONFLICT
);
}
else
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
/* Failed sign: expired key */
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_UNUSABLE_PUBKEY
);
}
else
{
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
SIGN_UIDS
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"sign_uid.expire"
))
{
next_state
=
SIGN_SET_EXPIRE
;
break
;
}
else
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"sign_uid.class"
))
{
next_state
=
SIGN_SET_CHECK_LEVEL
;
}
else
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"sign_uid.okay"
))
{
next_state
=
SIGN_CONFIRM
;
}
else
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
/* Failed sign: expired key */
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_UNUSABLE_PUBKEY
);
}
else
{
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
SIGN_SET_EXPIRE
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"sign_uid.class"
))
{
next_state
=
SIGN_SET_CHECK_LEVEL
;
}
else
{
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
SIGN_SET_CHECK_LEVEL
:
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"sign_uid.okay"
))
{
next_state
=
SIGN_CONFIRM
;
}
else
{
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
SIGN_CONFIRM
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
SIGN_QUIT
;
}
else
{
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
SIGN_QUIT
:
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"keyedit.save.okay"
))
{
next_state
=
SIGN_SAVE
;
}
else
{
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
SIGN_ERROR
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
/* Go to quit operation state */
next_state
=
SIGN_QUIT
;
}
else
{
next_state
=
SIGN_ERROR
;
}
break
;
default
:
next_state
=
SIGN_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
return
next_state
;
}
/* Change passphrase */
typedef
enum
{
PASSWD_START
,
PASSWD_COMMAND
,
PASSWD_ENTERNEW
,
PASSWD_QUIT
,
PASSWD_SAVE
,
PASSWD_ERROR
}
PasswdState
;
struct
passwd_parms_s
{
gpgme_passphrase_cb_t
func
;
void
*
opaque
;
};
static
gpg_error_t
edit_passwd_fnc_action
(
int
state
,
void
*
opaque
,
char
**
result
)
{
switch
(
state
)
{
case
PASSWD_COMMAND
:
/* Start the operation */
*
result
=
"passwd"
;
break
;
case
PASSWD_ENTERNEW
:
/* No action required. This state is only used by the
passphrase callback. */
break
;
case
PASSWD_QUIT
:
/* End the operation */
*
result
=
"quit"
;
break
;
case
PASSWD_SAVE
:
/* Save */
*
result
=
"Y"
;
break
;
case
PASSWD_ERROR
:
/* Special state: an error ocurred. Do nothing until we can quit */
break
;
default
:
/* Can't happen */
return
gpg_error
(
GPG_ERR_GENERAL
);
}
return
gpg_error
(
GPG_ERR_NO_ERROR
);
}
static
int
edit_passwd_fnc_transit
(
int
current_state
,
gpgme_status_code_t
status
,
const
char
*
args
,
void
*
opaque
,
gpg_error_t
*
err
)
{
int
next_state
;
switch
(
current_state
)
{
case
PASSWD_START
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
PASSWD_COMMAND
;
}
else
{
next_state
=
PASSWD_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
PASSWD_COMMAND
:
case
PASSWD_ENTERNEW
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
next_state
=
PASSWD_QUIT
;
}
else
if
(
status
==
GPGME_STATUS_NEED_PASSPHRASE_SYM
)
{
next_state
=
PASSWD_ENTERNEW
;
}
else
{
next_state
=
PASSWD_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
PASSWD_QUIT
:
if
(
status
==
GPGME_STATUS_GET_BOOL
&&
g_str_equal
(
args
,
"keyedit.save.okay"
))
{
next_state
=
PASSWD_SAVE
;
}
else
{
next_state
=
PASSWD_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
break
;
case
PASSWD_ERROR
:
if
(
status
==
GPGME_STATUS_GET_LINE
&&
g_str_equal
(
args
,
"keyedit.prompt"
))
{
/* Go to quit operation state */
next_state
=
PASSWD_QUIT
;
}
else
{
next_state
=
PASSWD_ERROR
;
}
break
;
default
:
next_state
=
PASSWD_ERROR
;
*
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
return
next_state
;
}
/* Release the edit parameters needed for setting owner trust. The prototype
* is that of a GpaContext's "done" signal handler.
*/
static
void
gpa_gpgme_edit_trust_parms_release
(
GpaContext
*
ctx
,
gpg_error_t
err
,
struct
edit_parms_s
*
parms
)
{
gpgme_data_release
(
parms
->
out
);
if
(
parms
->
signal_id
!=
0
)
{
/* Don't run this signal handler again if the context is reused */
g_signal_handler_disconnect
(
ctx
,
parms
->
signal_id
);
}
g_free
(
parms
->
opaque
);
g_free
(
parms
);
}
/* Generate the edit parameters needed for setting owner trust.
*/
static
struct
edit_parms_s
*
gpa_gpgme_edit_trust_parms_new
(
GpaContext
*
ctx
,
const
char
*
trust_string
,
gpgme_data_t
out
)
{
struct
edit_parms_s
*
edit_parms
=
g_malloc
(
sizeof
(
struct
edit_parms_s
));
edit_parms
->
state
=
TRUST_START
;
edit_parms
->
err
=
gpg_error
(
GPG_ERR_NO_ERROR
);
edit_parms
->
action
=
edit_trust_fnc_action
;
edit_parms
->
transit
=
edit_trust_fnc_transit
;
edit_parms
->
signal_id
=
0
;
edit_parms
->
out
=
out
;
edit_parms
->
opaque
=
g_strdup
(
trust_string
);
/* Make sure the cleanup is run when the edit completes */
edit_parms
->
signal_id
=
g_signal_connect
(
G_OBJECT
(
ctx
),
"done"
,
G_CALLBACK
(
gpa_gpgme_edit_trust_parms_release
),
edit_parms
);
return
edit_parms
;
}
/* Change the ownertrust of a key */
gpg_error_t
gpa_gpgme_edit_trust_start
(
GpaContext
*
ctx
,
gpgme_key_t
key
,
gpgme_validity_t
ownertrust
)
{
const
gchar
*
trust_strings
[]
=
{
"1"
,
"1"
,
"2"
,
"3"
,
"4"
,
"5"
};
struct
edit_parms_s
*
parms
=
NULL
;
gpg_error_t
err
;
gpgme_data_t
out
=
NULL
;
err
=
gpgme_data_new
(
&
out
);
if
(
gpg_err_code
(
err
)
!=
GPG_ERR_NO_ERROR
)
{
return
err
;
}
parms
=
gpa_gpgme_edit_trust_parms_new
(
ctx
,
trust_strings
[
ownertrust
],
out
);
err
=
gpgme_op_edit_start
(
ctx
->
ctx
,
key
,
edit_fnc
,
parms
,
out
);
return
err
;
}
/* Release the edit parameters needed for changing the expiry date. The
* prototype is that of a GpaContext's "done" signal handler.
*/
static
void
gpa_gpgme_edit_expire_parms_release
(
GpaContext
*
ctx
,
gpg_error_t
err
,
struct
edit_parms_s
*
parms
)
{
gpgme_data_release
(
parms
->
out
);
if
(
parms
->
signal_id
!=
0
)
{
/* Don't run this signal handler again if the context is reused */
g_signal_handler_disconnect
(
ctx
,
parms
->
signal_id
);
}
g_free
(
parms
->
opaque
);
g_free
(
parms
);
}
/* Generate the edit parameters needed for changing the expiry date.
*/
static
struct
edit_parms_s
*
gpa_gpgme_edit_expire_parms_new
(
GpaContext
*
ctx
,
GDate
*
date
,
gpgme_data_t
out
)
{
struct
edit_parms_s
*
edit_parms
=
g_malloc
(
sizeof
(
struct
edit_parms_s
));
int
buf_len
=
12
;
gchar
*
buf
=
g_malloc
(
buf_len
);
edit_parms
->
state
=
EXPIRE_START
;
edit_parms
->
err
=
gpg_error
(
GPG_ERR_NO_ERROR
);
edit_parms
->
action
=
edit_expire_fnc_action
;
edit_parms
->
transit
=
edit_expire_fnc_transit
;
edit_parms
->
signal_id
=
0
;
edit_parms
->
out
=
out
;
edit_parms
->
opaque
=
buf
;
/* The new expiration date */
if
(
date
)
{
g_date_strftime
(
buf
,
buf_len
,
"%Y-%m-%d"
,
date
);
}
else
{
strncpy
(
buf
,
"0"
,
buf_len
);
}
/* Make sure the cleanup is run when the edit completes */
edit_parms
->
signal_id
=
g_signal_connect
(
G_OBJECT
(
ctx
),
"done"
,
G_CALLBACK
(
gpa_gpgme_edit_expire_parms_release
),
edit_parms
);
return
edit_parms
;
}
/* Change the expire date of a key */
gpg_error_t
gpa_gpgme_edit_expire_start
(
GpaContext
*
ctx
,
gpgme_key_t
key
,
GDate
*
date
)
{
struct
edit_parms_s
*
parms
;
gpg_error_t
err
;
gpgme_data_t
out
=
NULL
;
err
=
gpgme_data_new
(
&
out
);
if
(
gpg_err_code
(
err
)
!=
GPG_ERR_NO_ERROR
)
{
return
err
;
}
parms
=
gpa_gpgme_edit_expire_parms_new
(
ctx
,
date
,
out
);
err
=
gpgme_op_edit_start
(
ctx
->
ctx
,
key
,
edit_fnc
,
parms
,
out
);
return
err
;
}
/* Release the edit parameters needed for signing. The prototype is that of
* a GpaContext's "done" signal handler.
*/
static
void
gpa_gpgme_edit_sign_parms_release
(
GpaContext
*
ctx
,
gpg_error_t
err
,
struct
edit_parms_s
*
parms
)
{
gpgme_data_release
(
parms
->
out
);
if
(
parms
->
signal_id
!=
0
)
{
g_signal_handler_disconnect
(
ctx
,
parms
->
signal_id
);
}
g_free
(
parms
->
opaque
);
g_free
(
parms
);
}
/* Generate the edit parameters needed for signing
*/
static
struct
edit_parms_s
*
gpa_gpgme_edit_sign_parms_new
(
GpaContext
*
ctx
,
char
*
check_level
,
gboolean
local
,
gpgme_data_t
out
)
{
struct
sign_parms_s
*
sign_parms
=
g_malloc
(
sizeof
(
struct
sign_parms_s
));
struct
edit_parms_s
*
edit_parms
=
g_malloc
(
sizeof
(
struct
edit_parms_s
));
edit_parms
->
state
=
SIGN_START
;
edit_parms
->
err
=
gpg_error
(
GPG_ERR_NO_ERROR
);
edit_parms
->
action
=
edit_sign_fnc_action
;
edit_parms
->
transit
=
edit_sign_fnc_transit
;
edit_parms
->
signal_id
=
0
;
edit_parms
->
out
=
out
;
edit_parms
->
opaque
=
sign_parms
;
sign_parms
->
check_level
=
check_level
;
sign_parms
->
local
=
local
;
/* Make sure the cleanup is run when the edit completes */
edit_parms
->
signal_id
=
g_signal_connect
(
G_OBJECT
(
ctx
),
"done"
,
G_CALLBACK
(
gpa_gpgme_edit_sign_parms_release
),
edit_parms
);
return
edit_parms
;
}
/* Sign this key with the given private key */
gpg_error_t
gpa_gpgme_edit_sign_start
(
GpaContext
*
ctx
,
gpgme_key_t
key
,
gpgme_key_t
secret_key
,
gboolean
local
)
{
struct
edit_parms_s
*
parms
=
NULL
;
gpg_error_t
err
=
gpg_error
(
GPG_ERR_NO_ERROR
);
gpgme_data_t
out
;
err
=
gpgme_data_new
(
&
out
);
if
(
gpg_err_code
(
err
)
!=
GPG_ERR_NO_ERROR
)
{
return
err
;
}
gpgme_signers_clear
(
ctx
->
ctx
);
err
=
gpgme_signers_add
(
ctx
->
ctx
,
secret_key
);
if
(
gpg_err_code
(
err
)
!=
GPG_ERR_NO_ERROR
)
{
return
err
;
}
parms
=
gpa_gpgme_edit_sign_parms_new
(
ctx
,
"0"
,
local
,
out
);
err
=
gpgme_op_edit_start
(
ctx
->
ctx
,
key
,
edit_fnc
,
parms
,
out
);
return
err
;
}
/*
* Change the passphrase of the key.
*/
/* Special passphrase callback for use within the passwd command */
gpg_error_t
passwd_passphrase_cb
(
void
*
hook
,
const
char
*
uid_hint
,
const
char
*
passphrase_info
,
int
prev_was_bad
,
int
fd
)
{
struct
edit_parms_s
*
parms
=
hook
;
if
(
parms
->
state
==
PASSWD_ENTERNEW
)
{
/* Gpg is asking for the new passphrase. Run the dialog to
enter and re-enter the new passphrase. */
return
gpa_change_passphrase_dialog_run
(
hook
,
uid_hint
,
passphrase_info
,
prev_was_bad
,
fd
);
}
else
{
/* Gpg is asking for the passphrase to unprotect the key. */
return
gpa_passphrase_cb
(
hook
,
uid_hint
,
passphrase_info
,
prev_was_bad
,
fd
);
}
}
/* Release the edit parameters needed for changing the passphrase. The
* prototype is that of a GpaContext's "done" signal handler.
*/
static
void
gpa_gpgme_edit_passwd_parms_release
(
GpaContext
*
ctx
,
gpg_error_t
err
,
struct
edit_parms_s
*
parms
)
{
struct
passwd_parms_s
*
passwd_parms
=
parms
->
opaque
;
gpgme_data_release
(
parms
->
out
);
/* Make sure the normal passphrase callback is used */
gpgme_set_passphrase_cb
(
ctx
->
ctx
,
passwd_parms
->
func
,
passwd_parms
->
opaque
);
if
(
parms
->
signal_id
!=
0
)
{
/* Don't run this signal handler again if the context is reused */
g_signal_handler_disconnect
(
ctx
,
parms
->
signal_id
);
}
g_free
(
parms
);
g_free
(
parms
->
opaque
);
}
/* Generate the edit parameters needed for changing the passphrase.
*/
static
struct
edit_parms_s
*
gpa_gpgme_edit_passwd_parms_new
(
GpaContext
*
ctx
,
gpgme_data_t
out
)
{
struct
edit_parms_s
*
edit_parms
=
g_malloc
(
sizeof
(
struct
edit_parms_s
));
struct
passwd_parms_s
*
passwd_parms
=
g_malloc
(
sizeof
(
struct
passwd_parms_s
));
edit_parms
->
state
=
PASSWD_START
;
edit_parms
->
err
=
gpg_error
(
GPG_ERR_NO_ERROR
);
edit_parms
->
action
=
edit_passwd_fnc_action
;
edit_parms
->
transit
=
edit_passwd_fnc_transit
;
edit_parms
->
signal_id
=
0
;
edit_parms
->
out
=
out
;
edit_parms
->
opaque
=
passwd_parms
;
gpgme_get_passphrase_cb
(
ctx
->
ctx
,
&
passwd_parms
->
func
,
&
passwd_parms
->
opaque
);
/* Make sure the cleanup is run when the edit completes */
edit_parms
->
signal_id
=
g_signal_connect
(
G_OBJECT
(
ctx
),
"done"
,
G_CALLBACK
(
gpa_gpgme_edit_passwd_parms_release
),
edit_parms
);
return
edit_parms
;
}
gpg_error_t
gpa_gpgme_edit_passwd_start
(
GpaContext
*
ctx
,
gpgme_key_t
key
)
{
struct
edit_parms_s
*
parms
;
gpg_error_t
err
;
gpgme_data_t
out
;
err
=
gpgme_data_new
(
&
out
);
if
(
gpg_err_code
(
err
)
!=
GPG_ERR_NO_ERROR
)
{
return
err
;
}
parms
=
gpa_gpgme_edit_passwd_parms_new
(
ctx
,
out
);
/* Use our own passphrase callback: The data are the actual edit
parms. */
gpgme_set_passphrase_cb
(
ctx
->
ctx
,
passwd_passphrase_cb
,
parms
);
err
=
gpgme_op_edit_start
(
ctx
->
ctx
,
key
,
edit_fnc
,
parms
,
out
);
return
err
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Mon, Dec 23, 1:25 PM (1 h, 54 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
c6/f3/87c4752bc47342cec5a36fac6143
Attached To
rGPA Gnu Privacy Assistant
Event Timeline
Log In to Comment