mirror of
git://git.gnupg.org/gnupg.git
synced 2024-11-04 20:38:50 +01:00
Merge branch 'STABLE-BRANCH-2-2' into master
This commit is contained in:
commit
d4dc4245bf
@ -453,9 +453,9 @@ void initialize_module_cache (void);
|
|||||||
void deinitialize_module_cache (void);
|
void deinitialize_module_cache (void);
|
||||||
void agent_cache_housekeeping (void);
|
void agent_cache_housekeeping (void);
|
||||||
void agent_flush_cache (void);
|
void agent_flush_cache (void);
|
||||||
int agent_put_cache (const char *key, cache_mode_t cache_mode,
|
int agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
|
||||||
const char *data, int ttl);
|
const char *data, int ttl);
|
||||||
char *agent_get_cache (const char *key, cache_mode_t cache_mode);
|
char *agent_get_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode);
|
||||||
void agent_store_cache_hit (const char *key);
|
void agent_store_cache_hit (const char *key);
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ struct cache_item_s {
|
|||||||
int ttl; /* max. lifetime given in seconds, -1 one means infinite */
|
int ttl; /* max. lifetime given in seconds, -1 one means infinite */
|
||||||
struct secret_data_s *pw;
|
struct secret_data_s *pw;
|
||||||
cache_mode_t cache_mode;
|
cache_mode_t cache_mode;
|
||||||
|
int restricted; /* The value of ctrl->restricted is part of the key. */
|
||||||
char key[1];
|
char key[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -202,8 +203,8 @@ housekeeping (void)
|
|||||||
if (r->pw && r->ttl >= 0 && r->accessed + r->ttl < current)
|
if (r->pw && r->ttl >= 0 && r->accessed + r->ttl < current)
|
||||||
{
|
{
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug (" expired '%s' (%ds after last access)\n",
|
log_debug (" expired '%s'.%d (%ds after last access)\n",
|
||||||
r->key, r->ttl);
|
r->key, r->restricted, r->ttl);
|
||||||
release_data (r->pw);
|
release_data (r->pw);
|
||||||
r->pw = NULL;
|
r->pw = NULL;
|
||||||
r->accessed = current;
|
r->accessed = current;
|
||||||
@ -224,8 +225,8 @@ housekeeping (void)
|
|||||||
if (r->pw && r->created + maxttl < current)
|
if (r->pw && r->created + maxttl < current)
|
||||||
{
|
{
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug (" expired '%s' (%lus after creation)\n",
|
log_debug (" expired '%s'.%d (%lus after creation)\n",
|
||||||
r->key, opt.max_cache_ttl);
|
r->key, r->restricted, opt.max_cache_ttl);
|
||||||
release_data (r->pw);
|
release_data (r->pw);
|
||||||
r->pw = NULL;
|
r->pw = NULL;
|
||||||
r->accessed = current;
|
r->accessed = current;
|
||||||
@ -233,15 +234,15 @@ housekeeping (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Third, make sure that we don't have too many items in the list.
|
/* Third, make sure that we don't have too many items in the list.
|
||||||
Expire old and unused entries after 30 minutes */
|
* Expire old and unused entries after 30 minutes. */
|
||||||
for (rprev=NULL, r=thecache; r; )
|
for (rprev=NULL, r=thecache; r; )
|
||||||
{
|
{
|
||||||
if (!r->pw && r->ttl >= 0 && r->accessed + 60*30 < current)
|
if (!r->pw && r->ttl >= 0 && r->accessed + 60*30 < current)
|
||||||
{
|
{
|
||||||
ITEM r2 = r->next;
|
ITEM r2 = r->next;
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug (" removed '%s' (mode %d) (slot not used for 30m)\n",
|
log_debug (" removed '%s'.%d (mode %d) (slot not used for 30m)\n",
|
||||||
r->key, r->cache_mode);
|
r->key, r->restricted, r->cache_mode);
|
||||||
xfree (r);
|
xfree (r);
|
||||||
if (!rprev)
|
if (!rprev)
|
||||||
thecache = r2;
|
thecache = r2;
|
||||||
@ -296,7 +297,7 @@ agent_flush_cache (void)
|
|||||||
if (r->pw)
|
if (r->pw)
|
||||||
{
|
{
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug (" flushing '%s'\n", r->key);
|
log_debug (" flushing '%s'.%d\n", r->key, r->restricted);
|
||||||
release_data (r->pw);
|
release_data (r->pw);
|
||||||
r->pw = NULL;
|
r->pw = NULL;
|
||||||
r->accessed = 0;
|
r->accessed = 0;
|
||||||
@ -326,20 +327,21 @@ cache_mode_equal (cache_mode_t a, cache_mode_t b)
|
|||||||
set infinite timeout. CACHE_MODE is stored with the cache entry
|
set infinite timeout. CACHE_MODE is stored with the cache entry
|
||||||
and used to select different timeouts. */
|
and used to select different timeouts. */
|
||||||
int
|
int
|
||||||
agent_put_cache (const char *key, cache_mode_t cache_mode,
|
agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
|
||||||
const char *data, int ttl)
|
const char *data, int ttl)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
ITEM r;
|
ITEM r;
|
||||||
int res;
|
int res;
|
||||||
|
int restricted = ctrl? ctrl->restricted : -1;
|
||||||
|
|
||||||
res = npth_mutex_lock (&cache_lock);
|
res = npth_mutex_lock (&cache_lock);
|
||||||
if (res)
|
if (res)
|
||||||
log_fatal ("failed to acquire cache mutex: %s\n", strerror (res));
|
log_fatal ("failed to acquire cache mutex: %s\n", strerror (res));
|
||||||
|
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug ("agent_put_cache '%s' (mode %d) requested ttl=%d\n",
|
log_debug ("agent_put_cache '%s'.%d (mode %d) requested ttl=%d\n",
|
||||||
key, cache_mode, ttl);
|
key, restricted, cache_mode, ttl);
|
||||||
housekeeping ();
|
housekeeping ();
|
||||||
|
|
||||||
if (!ttl)
|
if (!ttl)
|
||||||
@ -358,6 +360,7 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
|
|||||||
if (((cache_mode != CACHE_MODE_USER
|
if (((cache_mode != CACHE_MODE_USER
|
||||||
&& cache_mode != CACHE_MODE_NONCE)
|
&& cache_mode != CACHE_MODE_NONCE)
|
||||||
|| cache_mode_equal (r->cache_mode, cache_mode))
|
|| cache_mode_equal (r->cache_mode, cache_mode))
|
||||||
|
&& r->restricted == restricted
|
||||||
&& !strcmp (r->key, key))
|
&& !strcmp (r->key, key))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -386,6 +389,7 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
strcpy (r->key, key);
|
strcpy (r->key, key);
|
||||||
|
r->restricted = restricted;
|
||||||
r->created = r->accessed = gnupg_get_time ();
|
r->created = r->accessed = gnupg_get_time ();
|
||||||
r->ttl = ttl;
|
r->ttl = ttl;
|
||||||
r->cache_mode = cache_mode;
|
r->cache_mode = cache_mode;
|
||||||
@ -415,13 +419,14 @@ agent_put_cache (const char *key, cache_mode_t cache_mode,
|
|||||||
make use of CACHE_MODE except for CACHE_MODE_NONCE and
|
make use of CACHE_MODE except for CACHE_MODE_NONCE and
|
||||||
CACHE_MODE_USER. */
|
CACHE_MODE_USER. */
|
||||||
char *
|
char *
|
||||||
agent_get_cache (const char *key, cache_mode_t cache_mode)
|
agent_get_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
ITEM r;
|
ITEM r;
|
||||||
char *value = NULL;
|
char *value = NULL;
|
||||||
int res;
|
int res;
|
||||||
int last_stored = 0;
|
int last_stored = 0;
|
||||||
|
int restricted = ctrl? ctrl->restricted : -1;
|
||||||
|
|
||||||
if (cache_mode == CACHE_MODE_IGNORE)
|
if (cache_mode == CACHE_MODE_IGNORE)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -439,8 +444,8 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug ("agent_get_cache '%s' (mode %d)%s ...\n",
|
log_debug ("agent_get_cache '%s'.%d (mode %d)%s ...\n",
|
||||||
key, cache_mode,
|
key, ctrl->restricted, cache_mode,
|
||||||
last_stored? " (stored cache key)":"");
|
last_stored? " (stored cache key)":"");
|
||||||
housekeeping ();
|
housekeeping ();
|
||||||
|
|
||||||
@ -450,6 +455,7 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
|
|||||||
&& ((cache_mode != CACHE_MODE_USER
|
&& ((cache_mode != CACHE_MODE_USER
|
||||||
&& cache_mode != CACHE_MODE_NONCE)
|
&& cache_mode != CACHE_MODE_NONCE)
|
||||||
|| cache_mode_equal (r->cache_mode, cache_mode))
|
|| cache_mode_equal (r->cache_mode, cache_mode))
|
||||||
|
&& r->restricted == restricted
|
||||||
&& !strcmp (r->key, key))
|
&& !strcmp (r->key, key))
|
||||||
{
|
{
|
||||||
/* Note: To avoid races KEY may not be accessed anymore below. */
|
/* Note: To avoid races KEY may not be accessed anymore below. */
|
||||||
@ -472,8 +478,8 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
|
|||||||
{
|
{
|
||||||
xfree (value);
|
xfree (value);
|
||||||
value = NULL;
|
value = NULL;
|
||||||
log_error ("retrieving cache entry '%s' failed: %s\n",
|
log_error ("retrieving cache entry '%s'.%d failed: %s\n",
|
||||||
key, gpg_strerror (err));
|
key, restricted, gpg_strerror (err));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3145,7 +3145,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Cache this passphrase. */
|
/* Cache this passphrase. */
|
||||||
err = agent_put_cache (key_grip, CACHE_MODE_SSH, pi->pin, ttl);
|
err = agent_put_cache (ctrl, key_grip, CACHE_MODE_SSH, pi->pin, ttl);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -199,14 +199,14 @@ clear_nonce_cache (ctrl_t ctrl)
|
|||||||
{
|
{
|
||||||
if (ctrl->server_local->last_cache_nonce)
|
if (ctrl->server_local->last_cache_nonce)
|
||||||
{
|
{
|
||||||
agent_put_cache (ctrl->server_local->last_cache_nonce,
|
agent_put_cache (ctrl, ctrl->server_local->last_cache_nonce,
|
||||||
CACHE_MODE_NONCE, NULL, 0);
|
CACHE_MODE_NONCE, NULL, 0);
|
||||||
xfree (ctrl->server_local->last_cache_nonce);
|
xfree (ctrl->server_local->last_cache_nonce);
|
||||||
ctrl->server_local->last_cache_nonce = NULL;
|
ctrl->server_local->last_cache_nonce = NULL;
|
||||||
}
|
}
|
||||||
if (ctrl->server_local->last_passwd_nonce)
|
if (ctrl->server_local->last_passwd_nonce)
|
||||||
{
|
{
|
||||||
agent_put_cache (ctrl->server_local->last_passwd_nonce,
|
agent_put_cache (ctrl, ctrl->server_local->last_passwd_nonce,
|
||||||
CACHE_MODE_NONCE, NULL, 0);
|
CACHE_MODE_NONCE, NULL, 0);
|
||||||
xfree (ctrl->server_local->last_passwd_nonce);
|
xfree (ctrl->server_local->last_passwd_nonce);
|
||||||
ctrl->server_local->last_passwd_nonce = NULL;
|
ctrl->server_local->last_passwd_nonce = NULL;
|
||||||
@ -930,7 +930,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
|||||||
|
|
||||||
}
|
}
|
||||||
else if (passwd_nonce)
|
else if (passwd_nonce)
|
||||||
newpasswd = agent_get_cache (passwd_nonce, CACHE_MODE_NONCE);
|
newpasswd = agent_get_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE);
|
||||||
|
|
||||||
rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, no_protection,
|
rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, no_protection,
|
||||||
newpasswd, opt_preset, &outbuf);
|
newpasswd, opt_preset, &outbuf);
|
||||||
@ -1179,7 +1179,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
|
|||||||
/* Here we have a little race by doing the cache check separately
|
/* Here we have a little race by doing the cache check separately
|
||||||
from the retrieval function. Given that the cache flag is only a
|
from the retrieval function. Given that the cache flag is only a
|
||||||
hint, it should not really matter. */
|
hint, it should not really matter. */
|
||||||
pw = agent_get_cache (hexgrip, CACHE_MODE_NORMAL);
|
pw = agent_get_cache (ctrl, hexgrip, CACHE_MODE_NORMAL);
|
||||||
cached = pw ? "1" : "-";
|
cached = pw ? "1" : "-";
|
||||||
xfree (pw);
|
xfree (pw);
|
||||||
|
|
||||||
@ -1484,7 +1484,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
|
|||||||
if (!strcmp (desc, "X"))
|
if (!strcmp (desc, "X"))
|
||||||
desc = NULL;
|
desc = NULL;
|
||||||
|
|
||||||
pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_USER) : NULL;
|
pw = cacheid ? agent_get_cache (ctrl, cacheid, CACHE_MODE_USER) : NULL;
|
||||||
if (pw)
|
if (pw)
|
||||||
{
|
{
|
||||||
rc = send_back_passphrase (ctx, opt_data, pw);
|
rc = send_back_passphrase (ctx, opt_data, pw);
|
||||||
@ -1551,7 +1551,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
|
|||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
if (cacheid)
|
if (cacheid)
|
||||||
agent_put_cache (cacheid, CACHE_MODE_USER, response, 0);
|
agent_put_cache (ctrl, cacheid, CACHE_MODE_USER, response, 0);
|
||||||
rc = send_back_passphrase (ctx, opt_data, response);
|
rc = send_back_passphrase (ctx, opt_data, response);
|
||||||
}
|
}
|
||||||
xfree (response);
|
xfree (response);
|
||||||
@ -1593,7 +1593,8 @@ cmd_clear_passphrase (assuan_context_t ctx, char *line)
|
|||||||
if (!*cacheid || strlen (cacheid) > 50)
|
if (!*cacheid || strlen (cacheid) > 50)
|
||||||
return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
|
return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
|
||||||
|
|
||||||
agent_put_cache (cacheid, opt_normal ? CACHE_MODE_NORMAL : CACHE_MODE_USER,
|
agent_put_cache (ctrl, cacheid,
|
||||||
|
opt_normal ? CACHE_MODE_NORMAL : CACHE_MODE_USER,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
|
||||||
agent_clear_passphrase (ctrl, cacheid,
|
agent_clear_passphrase (ctrl, cacheid,
|
||||||
@ -1770,7 +1771,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
|
|||||||
passwd_nonce = bin2hex (buf, 12, NULL);
|
passwd_nonce = bin2hex (buf, 12, NULL);
|
||||||
}
|
}
|
||||||
if (passwd_nonce
|
if (passwd_nonce
|
||||||
&& !agent_put_cache (passwd_nonce, CACHE_MODE_NONCE,
|
&& !agent_put_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE,
|
||||||
passphrase, CACHE_TTL_NONCE))
|
passphrase, CACHE_TTL_NONCE))
|
||||||
{
|
{
|
||||||
assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
|
assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
|
||||||
@ -1785,7 +1786,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
|
|||||||
char *newpass = NULL;
|
char *newpass = NULL;
|
||||||
|
|
||||||
if (passwd_nonce)
|
if (passwd_nonce)
|
||||||
newpass = agent_get_cache (passwd_nonce, CACHE_MODE_NONCE);
|
newpass = agent_get_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE);
|
||||||
err = agent_protect_and_store (ctrl, s_skey, &newpass);
|
err = agent_protect_and_store (ctrl, s_skey, &newpass);
|
||||||
if (!err && passphrase)
|
if (!err && passphrase)
|
||||||
{
|
{
|
||||||
@ -1800,7 +1801,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
|
|||||||
cache_nonce = bin2hex (buf, 12, NULL);
|
cache_nonce = bin2hex (buf, 12, NULL);
|
||||||
}
|
}
|
||||||
if (cache_nonce
|
if (cache_nonce
|
||||||
&& !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
|
&& !agent_put_cache (ctrl, cache_nonce, CACHE_MODE_NONCE,
|
||||||
passphrase, CACHE_TTL_NONCE))
|
passphrase, CACHE_TTL_NONCE))
|
||||||
{
|
{
|
||||||
assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
|
assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
|
||||||
@ -1820,7 +1821,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
|
|||||||
passwd_nonce = bin2hex (buf, 12, NULL);
|
passwd_nonce = bin2hex (buf, 12, NULL);
|
||||||
}
|
}
|
||||||
if (passwd_nonce
|
if (passwd_nonce
|
||||||
&& !agent_put_cache (passwd_nonce, CACHE_MODE_NONCE,
|
&& !agent_put_cache (ctrl, passwd_nonce, CACHE_MODE_NONCE,
|
||||||
newpass, CACHE_TTL_NONCE))
|
newpass, CACHE_TTL_NONCE))
|
||||||
{
|
{
|
||||||
assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
|
assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
|
||||||
@ -1834,7 +1835,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
|
|||||||
{
|
{
|
||||||
char hexgrip[40+1];
|
char hexgrip[40+1];
|
||||||
bin2hex(grip, 20, hexgrip);
|
bin2hex(grip, 20, hexgrip);
|
||||||
err = agent_put_cache (hexgrip, CACHE_MODE_ANY, newpass,
|
err = agent_put_cache (ctrl, hexgrip, CACHE_MODE_ANY, newpass,
|
||||||
ctrl->cache_ttl_opt_preset);
|
ctrl->cache_ttl_opt_preset);
|
||||||
}
|
}
|
||||||
xfree (newpass);
|
xfree (newpass);
|
||||||
@ -1939,7 +1940,7 @@ cmd_preset_passphrase (assuan_context_t ctx, char *line)
|
|||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
|
rc = agent_put_cache (ctrl, grip_clear, CACHE_MODE_ANY, passphrase, ttl);
|
||||||
if (opt_inquire)
|
if (opt_inquire)
|
||||||
xfree (passphrase);
|
xfree (passphrase);
|
||||||
}
|
}
|
||||||
@ -2174,7 +2175,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
|||||||
cache_nonce = bin2hex (buf, 12, NULL);
|
cache_nonce = bin2hex (buf, 12, NULL);
|
||||||
}
|
}
|
||||||
if (cache_nonce
|
if (cache_nonce
|
||||||
&& !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
|
&& !agent_put_cache (ctrl, cache_nonce, CACHE_MODE_NONCE,
|
||||||
passphrase, CACHE_TTL_NONCE))
|
passphrase, CACHE_TTL_NONCE))
|
||||||
assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
|
assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
|
||||||
}
|
}
|
||||||
@ -2336,7 +2337,7 @@ cmd_export_key (assuan_context_t ctx, char *line)
|
|||||||
cache_nonce = bin2hex (buf, 12, NULL);
|
cache_nonce = bin2hex (buf, 12, NULL);
|
||||||
}
|
}
|
||||||
if (cache_nonce
|
if (cache_nonce
|
||||||
&& !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
|
&& !agent_put_cache (ctrl, cache_nonce, CACHE_MODE_NONCE,
|
||||||
passphrase, CACHE_TTL_NONCE))
|
passphrase, CACHE_TTL_NONCE))
|
||||||
{
|
{
|
||||||
assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
|
assuan_write_status (ctx, "CACHE_NONCE", cache_nonce);
|
||||||
@ -3101,6 +3102,21 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
|
|||||||
ctrl->s2k_count = 0;
|
ctrl->s2k_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!strcmp (key, "pretend-request-origin"))
|
||||||
|
{
|
||||||
|
log_assert (!ctrl->restricted);
|
||||||
|
switch (parse_request_origin (value))
|
||||||
|
{
|
||||||
|
case REQUEST_ORIGIN_LOCAL: ctrl->restricted = 0; break;
|
||||||
|
case REQUEST_ORIGIN_REMOTE: ctrl->restricted = 1; break;
|
||||||
|
case REQUEST_ORIGIN_BROWSER: ctrl->restricted = 2; break;
|
||||||
|
default:
|
||||||
|
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
/* Better pretend to be remote in case of a bad value. */
|
||||||
|
ctrl->restricted = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
|
err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
|
||||||
|
|
||||||
|
@ -951,7 +951,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, int dontcare_exist,
|
|||||||
{
|
{
|
||||||
char *cache_value;
|
char *cache_value;
|
||||||
|
|
||||||
cache_value = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
|
cache_value = agent_get_cache (ctrl, cache_nonce, CACHE_MODE_NONCE);
|
||||||
if (cache_value)
|
if (cache_value)
|
||||||
{
|
{
|
||||||
if (strlen (cache_value) < pi->max_length)
|
if (strlen (cache_value) < pi->max_length)
|
||||||
|
@ -511,7 +511,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
{
|
{
|
||||||
char *pw;
|
char *pw;
|
||||||
|
|
||||||
pw = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
|
pw = agent_get_cache (ctrl, cache_nonce, CACHE_MODE_NONCE);
|
||||||
if (pw)
|
if (pw)
|
||||||
{
|
{
|
||||||
rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
|
rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
|
||||||
@ -536,7 +536,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
char *pw;
|
char *pw;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
pw = agent_get_cache (hexgrip, cache_mode);
|
pw = agent_get_cache (ctrl, hexgrip, cache_mode);
|
||||||
if (pw)
|
if (pw)
|
||||||
{
|
{
|
||||||
rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
|
rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
|
||||||
@ -574,7 +574,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
We can often avoid the passphrase entry in the second
|
We can often avoid the passphrase entry in the second
|
||||||
step. We do this only in normal mode, so not to
|
step. We do this only in normal mode, so not to
|
||||||
interfere with unrelated cache entries. */
|
interfere with unrelated cache entries. */
|
||||||
pw = agent_get_cache (NULL, cache_mode);
|
pw = agent_get_cache (ctrl, NULL, cache_mode);
|
||||||
if (pw)
|
if (pw)
|
||||||
{
|
{
|
||||||
rc = agent_unprotect (ctrl, *keybuf, pw, NULL,
|
rc = agent_unprotect (ctrl, *keybuf, pw, NULL,
|
||||||
@ -670,7 +670,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Passphrase is fine. */
|
/* Passphrase is fine. */
|
||||||
agent_put_cache (hexgrip, cache_mode, pi->pin,
|
agent_put_cache (ctrl, hexgrip, cache_mode, pi->pin,
|
||||||
lookup_ttl? lookup_ttl (hexgrip) : 0);
|
lookup_ttl? lookup_ttl (hexgrip) : 0);
|
||||||
agent_store_cache_hit (hexgrip);
|
agent_store_cache_hit (hexgrip);
|
||||||
if (r_passphrase && *pi->pin)
|
if (r_passphrase && *pi->pin)
|
||||||
|
@ -468,7 +468,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
passphrase = NULL;
|
passphrase = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
passphrase_buffer = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
|
passphrase_buffer = agent_get_cache (ctrl, cache_nonce, CACHE_MODE_NONCE);
|
||||||
passphrase = passphrase_buffer;
|
passphrase = passphrase_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
}
|
}
|
||||||
if (cache_nonce
|
if (cache_nonce
|
||||||
&& !no_protection
|
&& !no_protection
|
||||||
&& !agent_put_cache (cache_nonce, CACHE_MODE_NONCE,
|
&& !agent_put_cache (ctrl, cache_nonce, CACHE_MODE_NONCE,
|
||||||
passphrase, ctrl->cache_ttl_opt_preset))
|
passphrase, ctrl->cache_ttl_opt_preset))
|
||||||
agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
|
agent_write_status (ctrl, "CACHE_NONCE", cache_nonce, NULL);
|
||||||
if (preset && !no_protection)
|
if (preset && !no_protection)
|
||||||
@ -538,7 +538,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
if (gcry_pk_get_keygrip (s_private, grip))
|
if (gcry_pk_get_keygrip (s_private, grip))
|
||||||
{
|
{
|
||||||
bin2hex(grip, 20, hexgrip);
|
bin2hex(grip, 20, hexgrip);
|
||||||
rc = agent_put_cache (hexgrip, CACHE_MODE_ANY, passphrase,
|
rc = agent_put_cache (ctrl, hexgrip, CACHE_MODE_ANY, passphrase,
|
||||||
ctrl->cache_ttl_opt_preset);
|
ctrl->cache_ttl_opt_preset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,8 +749,9 @@ agent_key_available (const unsigned char *grip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
agent_get_cache (const char *key, cache_mode_t cache_mode)
|
agent_get_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode)
|
||||||
{
|
{
|
||||||
|
(void)ctrl;
|
||||||
(void)key;
|
(void)key;
|
||||||
(void)cache_mode;
|
(void)cache_mode;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -69,3 +69,38 @@ str_pinentry_mode (pinentry_mode_t mode)
|
|||||||
}
|
}
|
||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse VALUE and return an integer representing a request_origin_t.
|
||||||
|
* (-1) is returned for an invalid VALUE. */
|
||||||
|
int
|
||||||
|
parse_request_origin (const char *value)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (!strcmp (value, "none") || !strcmp (value, "local"))
|
||||||
|
result = REQUEST_ORIGIN_LOCAL;
|
||||||
|
else if (!strcmp (value, "remote"))
|
||||||
|
result = REQUEST_ORIGIN_REMOTE;
|
||||||
|
else if (!strcmp (value, "browser"))
|
||||||
|
result = REQUEST_ORIGIN_BROWSER;
|
||||||
|
else
|
||||||
|
result = -1;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the string representation for the request origin. Returns
|
||||||
|
* "?" for an invalid mode. */
|
||||||
|
const char *
|
||||||
|
str_request_origin (request_origin_t mode)
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case REQUEST_ORIGIN_LOCAL: return "local";
|
||||||
|
case REQUEST_ORIGIN_REMOTE: return "remote";
|
||||||
|
case REQUEST_ORIGIN_BROWSER: return "browser";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
@ -39,10 +39,23 @@ typedef enum
|
|||||||
pinentry_mode_t;
|
pinentry_mode_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* Values for the request origin. */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
REQUEST_ORIGIN_LOCAL = 0,
|
||||||
|
REQUEST_ORIGIN_REMOTE,
|
||||||
|
REQUEST_ORIGIN_BROWSER
|
||||||
|
}
|
||||||
|
request_origin_t;
|
||||||
|
|
||||||
|
|
||||||
/*-- agent-opt.c --*/
|
/*-- agent-opt.c --*/
|
||||||
int parse_pinentry_mode (const char *value);
|
int parse_pinentry_mode (const char *value);
|
||||||
const char *str_pinentry_mode (pinentry_mode_t mode);
|
const char *str_pinentry_mode (pinentry_mode_t mode);
|
||||||
|
|
||||||
|
int parse_request_origin (const char *value);
|
||||||
|
const char *str_request_origin (request_origin_t mode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_SHAREDDEFS_H*/
|
#endif /*GNUPG_COMMON_SHAREDDEFS_H*/
|
||||||
|
@ -650,7 +650,7 @@ have_android_system=no
|
|||||||
use_simple_gettext=no
|
use_simple_gettext=no
|
||||||
use_ldapwrapper=yes
|
use_ldapwrapper=yes
|
||||||
mmap_needed=yes
|
mmap_needed=yes
|
||||||
require_pipe_to_unblock_pselect=no
|
require_pipe_to_unblock_pselect=yes
|
||||||
case "${host}" in
|
case "${host}" in
|
||||||
*-mingw32*)
|
*-mingw32*)
|
||||||
# special stuff for Windoze NT
|
# special stuff for Windoze NT
|
||||||
@ -665,6 +665,7 @@ case "${host}" in
|
|||||||
have_w32_system=yes
|
have_w32_system=yes
|
||||||
require_iconv=no
|
require_iconv=no
|
||||||
use_ldapwrapper=no # Fixme: Do this only for CE.
|
use_ldapwrapper=no # Fixme: Do this only for CE.
|
||||||
|
require_pipe_to_unblock_pselect=no
|
||||||
case "${host}" in
|
case "${host}" in
|
||||||
*-mingw32ce*)
|
*-mingw32ce*)
|
||||||
have_w32ce_system=yes
|
have_w32ce_system=yes
|
||||||
|
@ -85,7 +85,7 @@ DVIPS = TEXINPUTS="$(srcdir)$(PATH_SEPARATOR)$$TEXINPUTS" dvips
|
|||||||
AM_MAKEINFOFLAGS = -I $(srcdir) --css-ref=/share/site.css
|
AM_MAKEINFOFLAGS = -I $(srcdir) --css-ref=/share/site.css
|
||||||
|
|
||||||
YAT2M_OPTIONS = -I $(srcdir) \
|
YAT2M_OPTIONS = -I $(srcdir) \
|
||||||
--release "GnuPG @PACKAGE_VERSION@" --source "GNU Privacy Guard 2.1"
|
--release "GnuPG @PACKAGE_VERSION@" --source "GNU Privacy Guard 2.2"
|
||||||
|
|
||||||
myman_sources = gnupg7.texi gpg.texi gpgsm.texi gpg-agent.texi \
|
myman_sources = gnupg7.texi gpg.texi gpgsm.texi gpg-agent.texi \
|
||||||
dirmngr.texi scdaemon.texi tools.texi wks.texi
|
dirmngr.texi scdaemon.texi tools.texi wks.texi
|
||||||
|
@ -1581,6 +1581,27 @@ option is valid for the entire session or until reset to 0. This
|
|||||||
option is useful if the key is later used on boxes which are either
|
option is useful if the key is later used on boxes which are either
|
||||||
much slower or faster than the actual box.
|
much slower or faster than the actual box.
|
||||||
|
|
||||||
|
@item pretend-request-origin
|
||||||
|
This option switches the connection into a restricted mode which
|
||||||
|
handles all further commands in the same way as they would be handled
|
||||||
|
when originating from the extra or browser socket. Note that this
|
||||||
|
option is not available in the restricted mode. Valid values for this
|
||||||
|
option are:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item none
|
||||||
|
@itemx local
|
||||||
|
This is a NOP and leaves the connection in the standard way.
|
||||||
|
|
||||||
|
@item remote
|
||||||
|
Pretend to come from a remote origin in the same way as connections
|
||||||
|
from the @option{--extra-socket}.
|
||||||
|
|
||||||
|
@item browser
|
||||||
|
Pretend to come from a local web browser in the same way as connections
|
||||||
|
from the @option{--browser-socket}.
|
||||||
|
@end table
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
|
||||||
|
17
doc/gpg.texi
17
doc/gpg.texi
@ -1126,7 +1126,9 @@ all affected self-signatures is set one second ahead.
|
|||||||
@opindex passwd
|
@opindex passwd
|
||||||
Change the passphrase of the secret key belonging to the certificate
|
Change the passphrase of the secret key belonging to the certificate
|
||||||
specified as @var{user-id}. This is a shortcut for the sub-command
|
specified as @var{user-id}. This is a shortcut for the sub-command
|
||||||
@code{passwd} of the edit key menu.
|
@code{passwd} of the edit key menu. When using together with the
|
||||||
|
option @option{--dry-run} this will not actually change the passphrase
|
||||||
|
but check that the current passphrase is correct.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@ -2213,8 +2215,8 @@ handy in case where an encrypted message contains a bogus key ID.
|
|||||||
@opindex skip-hidden-recipients
|
@opindex skip-hidden-recipients
|
||||||
@opindex no-skip-hidden-recipients
|
@opindex no-skip-hidden-recipients
|
||||||
During decryption skip all anonymous recipients. This option helps in
|
During decryption skip all anonymous recipients. This option helps in
|
||||||
the case that people use the hidden recipients feature to hide there
|
the case that people use the hidden recipients feature to hide their
|
||||||
own encrypt-to key from others. If oneself has many secret keys this
|
own encrypt-to key from others. If one has many secret keys this
|
||||||
may lead to a major annoyance because all keys are tried in turn to
|
may lead to a major annoyance because all keys are tried in turn to
|
||||||
decrypt something which was not really intended for it. The drawback
|
decrypt something which was not really intended for it. The drawback
|
||||||
of this option is that it is currently not possible to decrypt a
|
of this option is that it is currently not possible to decrypt a
|
||||||
@ -3177,6 +3179,15 @@ are:
|
|||||||
Pinentry the user is not prompted again if he enters a bad password.
|
Pinentry the user is not prompted again if he enters a bad password.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@item --request-origin @var{origin}
|
||||||
|
@opindex request-origin
|
||||||
|
Tell gpg to assume that the operation ultimately originated at
|
||||||
|
@var{origin}. Depending on the origin certain restrictions are applied
|
||||||
|
and the Pinentry may include an extra note on the origin. Supported
|
||||||
|
values for @var{origin} are: @code{local} which is the default,
|
||||||
|
@code{remote} to indicate a remote origin or @code{browser} for an
|
||||||
|
operation requested by a web browser.
|
||||||
|
|
||||||
@item --command-fd @var{n}
|
@item --command-fd @var{n}
|
||||||
@opindex command-fd
|
@opindex command-fd
|
||||||
This is a replacement for the deprecated shared-memory IPC mode.
|
This is a replacement for the deprecated shared-memory IPC mode.
|
||||||
|
@ -765,6 +765,15 @@ are:
|
|||||||
Pinentry the user is not prompted again if he enters a bad password.
|
Pinentry the user is not prompted again if he enters a bad password.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@item --request-origin @var{origin}
|
||||||
|
@opindex request-origin
|
||||||
|
Tell gpgsm to assume that the operation ultimately originated at
|
||||||
|
@var{origin}. Depending on the origin certain restrictions are applied
|
||||||
|
and the Pinentry may include an extra note on the origin. Supported
|
||||||
|
values for @var{origin} are: @code{local} which is the default,
|
||||||
|
@code{remote} to indicate a remote origin or @code{browser} for an
|
||||||
|
operation requested by a web browser.
|
||||||
|
|
||||||
@item --no-common-certs-import
|
@item --no-common-certs-import
|
||||||
@opindex no-common-certs-import
|
@opindex no-common-certs-import
|
||||||
Suppress the import of common certificates on keybox creation.
|
Suppress the import of common certificates on keybox creation.
|
||||||
|
@ -289,6 +289,23 @@ start_agent (ctrl_t ctrl, int flag_for_card)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pass on the request origin. */
|
||||||
|
if (opt.request_origin)
|
||||||
|
{
|
||||||
|
char *tmp = xasprintf ("OPTION pretend-request-origin=%s",
|
||||||
|
str_request_origin (opt.request_origin));
|
||||||
|
rc = assuan_transact (agent_ctx, tmp,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
xfree (tmp);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
log_error ("setting request origin '%s' failed: %s\n",
|
||||||
|
str_request_origin (opt.request_origin),
|
||||||
|
gpg_strerror (rc));
|
||||||
|
write_status_error ("set_request_origin", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* In DE_VS mode under Windows we require that the JENT RNG
|
/* In DE_VS mode under Windows we require that the JENT RNG
|
||||||
* is active. */
|
* is active. */
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
@ -591,6 +608,8 @@ learn_status_cb (void *opaque, const char *line)
|
|||||||
parm->extcap.ki = abool;
|
parm->extcap.ki = abool;
|
||||||
else if (!strcmp (p, "aac"))
|
else if (!strcmp (p, "aac"))
|
||||||
parm->extcap.aac = abool;
|
parm->extcap.aac = abool;
|
||||||
|
else if (!strcmp (p, "kdf"))
|
||||||
|
parm->extcap.kdf = abool;
|
||||||
else if (!strcmp (p, "si"))
|
else if (!strcmp (p, "si"))
|
||||||
parm->status_indicator = strtoul (p2, NULL, 10);
|
parm->status_indicator = strtoul (p2, NULL, 10);
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ struct agent_card_info_s
|
|||||||
struct {
|
struct {
|
||||||
unsigned int ki:1; /* Key import available. */
|
unsigned int ki:1; /* Key import available. */
|
||||||
unsigned int aac:1; /* Algorithm attributes are changeable. */
|
unsigned int aac:1; /* Algorithm attributes are changeable. */
|
||||||
|
unsigned int kdf:1; /* KDF object to support PIN hashing available. */
|
||||||
} extcap;
|
} extcap;
|
||||||
unsigned int status_indicator;
|
unsigned int status_indicator;
|
||||||
};
|
};
|
||||||
|
132
g10/card-util.c
132
g10/card-util.c
@ -659,7 +659,7 @@ current_card_status (ctrl_t ctrl, estream_t fp,
|
|||||||
|
|
||||||
/* Print all available information for specific card with SERIALNO.
|
/* Print all available information for specific card with SERIALNO.
|
||||||
Print all available information for current card when SERIALNO is NULL.
|
Print all available information for current card when SERIALNO is NULL.
|
||||||
Or print llfor all cards when SERIALNO is "all". */
|
Or print for all cards when SERIALNO is "all". */
|
||||||
void
|
void
|
||||||
card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
|
card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
|
||||||
{
|
{
|
||||||
@ -1797,6 +1797,7 @@ factory_reset (void)
|
|||||||
scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
|
scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
|
||||||
scd apdu 00 e6 00 00
|
scd apdu 00 e6 00 00
|
||||||
scd apdu 00 44 00 00
|
scd apdu 00 44 00 00
|
||||||
|
scd reset
|
||||||
/echo Card has been reset to factory defaults
|
/echo Card has been reset to factory defaults
|
||||||
|
|
||||||
but tries to find out something about the card first.
|
but tries to find out something about the card first.
|
||||||
@ -1809,7 +1810,7 @@ factory_reset (void)
|
|||||||
else if (err)
|
else if (err)
|
||||||
{
|
{
|
||||||
log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (err));
|
log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (err));
|
||||||
return;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!termstate)
|
if (!termstate)
|
||||||
@ -1859,10 +1860,16 @@ factory_reset (void)
|
|||||||
command because there is no machinery in scdaemon to catch
|
command because there is no machinery in scdaemon to catch
|
||||||
the verify command and ask for the PIN when the "APDU"
|
the verify command and ask for the PIN when the "APDU"
|
||||||
command is used. */
|
command is used. */
|
||||||
|
/* Here, the length of dummy wrong PIN is 32-byte, also
|
||||||
|
supporting authentication with KDF DO. */
|
||||||
for (i=0; i < 4; i++)
|
for (i=0; i < 4; i++)
|
||||||
send_apdu ("00200081084040404040404040", "VERIFY", 0xffff);
|
send_apdu ("0020008120"
|
||||||
|
"40404040404040404040404040404040"
|
||||||
|
"40404040404040404040404040404040", "VERIFY", 0xffff);
|
||||||
for (i=0; i < 4; i++)
|
for (i=0; i < 4; i++)
|
||||||
send_apdu ("00200083084040404040404040", "VERIFY", 0xffff);
|
send_apdu ("0020008320"
|
||||||
|
"40404040404040404040404040404040"
|
||||||
|
"40404040404040404040404040404040", "VERIFY", 0xffff);
|
||||||
|
|
||||||
/* Send terminate datafile command. */
|
/* Send terminate datafile command. */
|
||||||
err = send_apdu ("00e60000", "TERMINATE DF", 0x6985);
|
err = send_apdu ("00e60000", "TERMINATE DF", 0x6985);
|
||||||
@ -1878,8 +1885,16 @@ factory_reset (void)
|
|||||||
|
|
||||||
/* Finally we reset the card reader once more. */
|
/* Finally we reset the card reader once more. */
|
||||||
err = send_apdu (NULL, "RESET", 0);
|
err = send_apdu (NULL, "RESET", 0);
|
||||||
if (err)
|
|
||||||
goto leave;
|
/* Then, connect the card again. */
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
char *serialno0;
|
||||||
|
|
||||||
|
err = agent_scd_serialno (&serialno0, NULL);
|
||||||
|
if (!err)
|
||||||
|
xfree (serialno0);
|
||||||
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
xfree (answer);
|
xfree (answer);
|
||||||
@ -1887,6 +1902,104 @@ factory_reset (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define USER_PIN_DEFAULT "123456"
|
||||||
|
#define ADMIN_PIN_DEFAULT "12345678"
|
||||||
|
#define KDF_DATA_LENGTH 110
|
||||||
|
|
||||||
|
/* Generate KDF data. */
|
||||||
|
static gpg_error_t
|
||||||
|
gen_kdf_data (unsigned char *data)
|
||||||
|
{
|
||||||
|
const unsigned char h0[] = { 0x81, 0x01, 0x03,
|
||||||
|
0x82, 0x01, 0x08,
|
||||||
|
0x83, 0x04 };
|
||||||
|
const unsigned char h1[] = { 0x84, 0x08 };
|
||||||
|
const unsigned char h2[] = { 0x85, 0x08 };
|
||||||
|
const unsigned char h3[] = { 0x86, 0x08 };
|
||||||
|
const unsigned char h4[] = { 0x87, 0x20 };
|
||||||
|
const unsigned char h5[] = { 0x88, 0x20 };
|
||||||
|
unsigned char *p, *salt_user, *salt_admin;
|
||||||
|
unsigned char s2k_char;
|
||||||
|
unsigned int iterations;
|
||||||
|
unsigned char count_4byte[4];
|
||||||
|
gpg_error_t err = 0;
|
||||||
|
|
||||||
|
p = data;
|
||||||
|
|
||||||
|
s2k_char = encode_s2k_iterations (0);
|
||||||
|
iterations = S2K_DECODE_COUNT (s2k_char);
|
||||||
|
count_4byte[0] = (iterations >> 24) & 0xff;
|
||||||
|
count_4byte[1] = (iterations >> 16) & 0xff;
|
||||||
|
count_4byte[2] = (iterations >> 8) & 0xff;
|
||||||
|
count_4byte[3] = (iterations & 0xff);
|
||||||
|
|
||||||
|
memcpy (p, h0, sizeof h0);
|
||||||
|
p += sizeof h0;
|
||||||
|
memcpy (p, count_4byte, sizeof count_4byte);
|
||||||
|
p += sizeof count_4byte;
|
||||||
|
memcpy (p, h1, sizeof h1);
|
||||||
|
salt_user = (p += sizeof h1);
|
||||||
|
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
||||||
|
p += 8;
|
||||||
|
memcpy (p, h2, sizeof h2);
|
||||||
|
p += sizeof h2;
|
||||||
|
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
||||||
|
p += 8;
|
||||||
|
memcpy (p, h3, sizeof h3);
|
||||||
|
salt_admin = (p += sizeof h3);
|
||||||
|
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
||||||
|
p += 8;
|
||||||
|
memcpy (p, h4, sizeof h4);
|
||||||
|
p += sizeof h4;
|
||||||
|
err = gcry_kdf_derive (USER_PIN_DEFAULT, strlen (USER_PIN_DEFAULT),
|
||||||
|
GCRY_KDF_ITERSALTED_S2K, DIGEST_ALGO_SHA256,
|
||||||
|
salt_user, 8, iterations, 32, p);
|
||||||
|
p += 32;
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
memcpy (p, h5, sizeof h5);
|
||||||
|
p += sizeof h5;
|
||||||
|
err = gcry_kdf_derive (ADMIN_PIN_DEFAULT, strlen (ADMIN_PIN_DEFAULT),
|
||||||
|
GCRY_KDF_ITERSALTED_S2K, DIGEST_ALGO_SHA256,
|
||||||
|
salt_admin, 8, iterations, 32, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup KDF data object which is used for PIN authentication. */
|
||||||
|
static void
|
||||||
|
kdf_setup (void)
|
||||||
|
{
|
||||||
|
struct agent_card_info_s info;
|
||||||
|
gpg_error_t err;
|
||||||
|
unsigned char kdf_data[KDF_DATA_LENGTH];
|
||||||
|
|
||||||
|
memset (&info, 0, sizeof info);
|
||||||
|
|
||||||
|
err = agent_scd_getattr ("EXTCAP", &info);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error (_("error getting card info: %s\n"), gpg_strerror (err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.extcap.kdf)
|
||||||
|
{
|
||||||
|
log_error (_("This command is not supported by this card\n"));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(err = gen_kdf_data (kdf_data))
|
||||||
|
&& !(err = agent_scd_setattr ("KDF", kdf_data, KDF_DATA_LENGTH, NULL)))
|
||||||
|
err = agent_scd_getattr ("KDF", &info);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
log_error (_("error for setup KDF: %s\n"), gpg_strerror (err));
|
||||||
|
|
||||||
|
leave:
|
||||||
|
agent_release_card_info (&info);
|
||||||
|
}
|
||||||
|
|
||||||
/* Data used by the command parser. This needs to be outside of the
|
/* Data used by the command parser. This needs to be outside of the
|
||||||
function scope to allow readline based command completion. */
|
function scope to allow readline based command completion. */
|
||||||
@ -1896,7 +2009,7 @@ enum cmdids
|
|||||||
cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY,
|
cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY,
|
||||||
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
|
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
|
||||||
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
|
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
|
||||||
cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET,
|
cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET, cmdKDFSETUP,
|
||||||
cmdINVCMD
|
cmdINVCMD
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1930,6 +2043,7 @@ static struct
|
|||||||
{ "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")},
|
{ "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")},
|
||||||
{ "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") },
|
{ "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") },
|
||||||
{ "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")},
|
{ "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")},
|
||||||
|
{ "kdf-setup", cmdKDFSETUP, 1, N_("setup KDF for PIN authentication")},
|
||||||
/* Note, that we do not announce these command yet. */
|
/* Note, that we do not announce these command yet. */
|
||||||
{ "privatedo", cmdPRIVATEDO, 0, NULL },
|
{ "privatedo", cmdPRIVATEDO, 0, NULL },
|
||||||
{ "readcert", cmdREADCERT, 0, NULL },
|
{ "readcert", cmdREADCERT, 0, NULL },
|
||||||
@ -2213,6 +2327,10 @@ card_edit (ctrl_t ctrl, strlist_t commands)
|
|||||||
factory_reset ();
|
factory_reset ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case cmdKDFSETUP:
|
||||||
|
kdf_setup ();
|
||||||
|
break;
|
||||||
|
|
||||||
case cmdQUIT:
|
case cmdQUIT:
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
@ -428,6 +428,7 @@ enum cmd_and_opt_values
|
|||||||
oDisableSignerUID,
|
oDisableSignerUID,
|
||||||
oSender,
|
oSender,
|
||||||
oKeyOrigin,
|
oKeyOrigin,
|
||||||
|
oRequestOrigin,
|
||||||
|
|
||||||
oNoop
|
oNoop
|
||||||
};
|
};
|
||||||
@ -719,6 +720,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"),
|
ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"),
|
||||||
ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"),
|
ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"),
|
||||||
ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"),
|
ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"),
|
||||||
|
ARGPARSE_s_s (oRequestOrigin, "request-origin", "@"),
|
||||||
ARGPARSE_s_i (oCommandFD, "command-fd", "@"),
|
ARGPARSE_s_i (oCommandFD, "command-fd", "@"),
|
||||||
ARGPARSE_s_s (oCommandFile, "command-file", "@"),
|
ARGPARSE_s_s (oCommandFile, "command-file", "@"),
|
||||||
ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
|
ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
|
||||||
@ -3158,6 +3160,12 @@ main (int argc, char **argv)
|
|||||||
log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
|
log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oRequestOrigin:
|
||||||
|
opt.request_origin = parse_request_origin (pargs.r.ret_str);
|
||||||
|
if (opt.request_origin == -1)
|
||||||
|
log_error (_("invalid request origin '%s'\n"), pargs.r.ret_str);
|
||||||
|
break;
|
||||||
|
|
||||||
case oCommandFD:
|
case oCommandFD:
|
||||||
opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
|
opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
|
||||||
if (! gnupg_fd_valid (opt.command_fd))
|
if (! gnupg_fd_valid (opt.command_fd))
|
||||||
|
@ -24,6 +24,10 @@
|
|||||||
correct value and may be of advantage if we ever have to do
|
correct value and may be of advantage if we ever have to do
|
||||||
special things. */
|
special things. */
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
# define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef GPG_ERR_SOURCE_DEFAULT
|
#ifdef GPG_ERR_SOURCE_DEFAULT
|
||||||
#error GPG_ERR_SOURCE_DEFAULT already defined
|
#error GPG_ERR_SOURCE_DEFAULT already defined
|
||||||
#endif
|
#endif
|
||||||
|
@ -1134,8 +1134,10 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
|
|||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
/* Note that when using --dry-run we don't change the
|
||||||
|
* passphrase but merely verify the current passphrase. */
|
||||||
desc = gpg_format_keydesc (ctrl, pk, FORMAT_KEYDESC_NORMAL, 1);
|
desc = gpg_format_keydesc (ctrl, pk, FORMAT_KEYDESC_NORMAL, 1);
|
||||||
err = agent_passwd (ctrl, hexgrip, desc, 0,
|
err = agent_passwd (ctrl, hexgrip, desc, !!opt.dry_run,
|
||||||
&cache_nonce, &passwd_nonce);
|
&cache_nonce, &passwd_nonce);
|
||||||
xfree (desc);
|
xfree (desc);
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#ifdef HAVE_WINSOCK2_H
|
#ifdef HAVE_WINSOCK2_H
|
||||||
|
# define WIN32_LEAN_AND_MEAN 1
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -278,6 +278,7 @@ struct
|
|||||||
|
|
||||||
int passphrase_repeat;
|
int passphrase_repeat;
|
||||||
int pinentry_mode;
|
int pinentry_mode;
|
||||||
|
int request_origin;
|
||||||
|
|
||||||
int unwrap_encryption;
|
int unwrap_encryption;
|
||||||
int only_sign_text_ids;
|
int only_sign_text_ids;
|
||||||
|
@ -971,10 +971,10 @@ skip_packet (IOBUF inp, int pkttype, unsigned long pktlen, int partial)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read PKTLEN bytes form INP and return them in a newly allocated
|
/* Read PKTLEN bytes from INP and return them in a newly allocated
|
||||||
buffer. In case of an error (including reading fewer than PKTLEN
|
* buffer. In case of an error (including reading fewer than PKTLEN
|
||||||
bytes from INP before EOF is returned), NULL is returned and an
|
* bytes from INP before EOF is returned), NULL is returned and an
|
||||||
error message is logged. */
|
* error message is logged. */
|
||||||
static void *
|
static void *
|
||||||
read_rest (IOBUF inp, size_t pktlen)
|
read_rest (IOBUF inp, size_t pktlen)
|
||||||
{
|
{
|
||||||
@ -1741,6 +1741,8 @@ enum_sig_subpkt (const subpktarea_t * pktbuf, sigsubpkttype_t reqtype,
|
|||||||
}
|
}
|
||||||
if (buflen < n)
|
if (buflen < n)
|
||||||
goto too_short;
|
goto too_short;
|
||||||
|
if (!buflen)
|
||||||
|
goto no_type_byte;
|
||||||
type = *buffer;
|
type = *buffer;
|
||||||
if (type & 0x80)
|
if (type & 0x80)
|
||||||
{
|
{
|
||||||
@ -1815,6 +1817,13 @@ enum_sig_subpkt (const subpktarea_t * pktbuf, sigsubpkttype_t reqtype,
|
|||||||
if (start)
|
if (start)
|
||||||
*start = -1;
|
*start = -1;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
no_type_byte:
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("type octet missing in subpacket\n");
|
||||||
|
if (start)
|
||||||
|
*start = -1;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ import_ownertrust (ctrl_t ctrl, const char *fname )
|
|||||||
while (fprlen < MAX_FINGERPRINT_LEN)
|
while (fprlen < MAX_FINGERPRINT_LEN)
|
||||||
fpr[fprlen++] = 0;
|
fpr[fprlen++] = 0;
|
||||||
|
|
||||||
rc = tdbio_search_trust_byfpr (fpr, &rec);
|
rc = tdbio_search_trust_byfpr (ctrl, fpr, &rec);
|
||||||
if( !rc ) { /* found: update */
|
if( !rc ) { /* found: update */
|
||||||
if (rec.r.trust.ownertrust != otrust)
|
if (rec.r.trust.ownertrust != otrust)
|
||||||
{
|
{
|
||||||
|
104
g10/tdbio.c
104
g10/tdbio.c
@ -105,16 +105,17 @@ struct cmp_xdir_struct
|
|||||||
/* The name of the trustdb file. */
|
/* The name of the trustdb file. */
|
||||||
static char *db_name;
|
static char *db_name;
|
||||||
|
|
||||||
/* The handle for locking the trustdb file and a flag to record
|
/* The handle for locking the trustdb file and a counter to record how
|
||||||
whether a lock has been taken. */
|
* often this lock has been taken. That counter is required becuase
|
||||||
|
* dotlock does not implemen recursive locks. */
|
||||||
static dotlock_t lockhandle;
|
static dotlock_t lockhandle;
|
||||||
static int is_locked;
|
static unsigned int is_locked;
|
||||||
|
|
||||||
/* The file descriptor of the trustdb. */
|
/* The file descriptor of the trustdb. */
|
||||||
static int db_fd = -1;
|
static int db_fd = -1;
|
||||||
|
|
||||||
/* A flag indicating that a transaction is active. */
|
/* A flag indicating that a transaction is active. */
|
||||||
static int in_transaction;
|
/* static int in_transaction; Not yet used. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ static void create_hashtable (ctrl_t ctrl, TRUSTREC *vr, int type);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Take a lock on the trustdb file name. I a lock file can't be
|
* Take a lock on the trustdb file name. I a lock file can't be
|
||||||
* created the function terminates the process. Excvept for a
|
* created the function terminates the process. Except for a
|
||||||
* different return code the function does nothing if the lock has
|
* different return code the function does nothing if the lock has
|
||||||
* already been taken.
|
* already been taken.
|
||||||
*
|
*
|
||||||
@ -135,6 +136,8 @@ static void create_hashtable (ctrl_t ctrl, TRUSTREC *vr, int type);
|
|||||||
static int
|
static int
|
||||||
take_write_lock (void)
|
take_write_lock (void)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!lockhandle)
|
if (!lockhandle)
|
||||||
lockhandle = dotlock_create (db_name, 0);
|
lockhandle = dotlock_create (db_name, 0);
|
||||||
if (!lockhandle)
|
if (!lockhandle)
|
||||||
@ -144,12 +147,16 @@ take_write_lock (void)
|
|||||||
{
|
{
|
||||||
if (dotlock_take (lockhandle, -1) )
|
if (dotlock_take (lockhandle, -1) )
|
||||||
log_fatal ( _("can't lock '%s'\n"), db_name );
|
log_fatal ( _("can't lock '%s'\n"), db_name );
|
||||||
else
|
rc = 0;
|
||||||
is_locked = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 1;
|
rc = 1;
|
||||||
|
|
||||||
|
if (opt.lock_once)
|
||||||
|
is_locked = 1;
|
||||||
|
else
|
||||||
|
is_locked++;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,10 +167,22 @@ take_write_lock (void)
|
|||||||
static void
|
static void
|
||||||
release_write_lock (void)
|
release_write_lock (void)
|
||||||
{
|
{
|
||||||
if (!opt.lock_once)
|
if (opt.lock_once)
|
||||||
if (!dotlock_release (lockhandle))
|
return; /* Don't care; here IS_LOCKED is fixed to 1. */
|
||||||
is_locked = 0;
|
|
||||||
|
if (!is_locked)
|
||||||
|
{
|
||||||
|
log_error ("Ooops, tdbio:release_write_lock with no lock held\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (--is_locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dotlock_release (lockhandle))
|
||||||
|
log_error ("Oops, tdbio:release_write_locked failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
************* record cache **********
|
************* record cache **********
|
||||||
@ -329,6 +348,7 @@ put_record_into_cache (ulong recno, const char *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* No clean entries: We have to flush some dirty entries. */
|
/* No clean entries: We have to flush some dirty entries. */
|
||||||
|
#if 0 /* Transactions are not yet used. */
|
||||||
if (in_transaction)
|
if (in_transaction)
|
||||||
{
|
{
|
||||||
/* But we can't do this while in a transaction. Thus we
|
/* But we can't do this while in a transaction. Thus we
|
||||||
@ -352,6 +372,7 @@ put_record_into_cache (ulong recno, const char *data)
|
|||||||
log_info (_("trustdb transaction too large\n"));
|
log_info (_("trustdb transaction too large\n"));
|
||||||
return GPG_ERR_RESOURCE_LIMIT;
|
return GPG_ERR_RESOURCE_LIMIT;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dirty_count)
|
if (dirty_count)
|
||||||
{
|
{
|
||||||
@ -418,8 +439,10 @@ tdbio_sync()
|
|||||||
|
|
||||||
if( db_fd == -1 )
|
if( db_fd == -1 )
|
||||||
open_db();
|
open_db();
|
||||||
|
#if 0 /* Transactions are not yet used. */
|
||||||
if( in_transaction )
|
if( in_transaction )
|
||||||
log_bug("tdbio: syncing while in transaction\n");
|
log_bug("tdbio: syncing while in transaction\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
if( !cache_is_dirty )
|
if( !cache_is_dirty )
|
||||||
return 0;
|
return 0;
|
||||||
@ -560,7 +583,7 @@ tdbio_update_version_record (ctrl_t ctrl)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Create and write the trustdb version record.
|
* Create and write the trustdb version record.
|
||||||
*
|
* This is called with the writelock activ.
|
||||||
* Returns: 0 on success or an error code.
|
* Returns: 0 on success or an error code.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -951,10 +974,12 @@ tdbio_write_nextcheck (ctrl_t ctrl, ulong stamp)
|
|||||||
* Return: record number
|
* Return: record number
|
||||||
*/
|
*/
|
||||||
static ulong
|
static ulong
|
||||||
get_trusthashrec(void)
|
get_trusthashrec (ctrl_t ctrl)
|
||||||
{
|
{
|
||||||
static ulong trusthashtbl; /* Record number of the trust hashtable. */
|
static ulong trusthashtbl; /* Record number of the trust hashtable. */
|
||||||
|
|
||||||
|
(void)ctrl;
|
||||||
|
|
||||||
if (!trusthashtbl)
|
if (!trusthashtbl)
|
||||||
{
|
{
|
||||||
TRUSTREC vr;
|
TRUSTREC vr;
|
||||||
@ -965,6 +990,20 @@ get_trusthashrec(void)
|
|||||||
log_fatal (_("%s: error reading version record: %s\n"),
|
log_fatal (_("%s: error reading version record: %s\n"),
|
||||||
db_name, gpg_strerror (rc) );
|
db_name, gpg_strerror (rc) );
|
||||||
|
|
||||||
|
if (!vr.r.ver.trusthashtbl)
|
||||||
|
{
|
||||||
|
/* Oops: the trustdb is corrupt because the hashtable is
|
||||||
|
* always created along with the version record. However,
|
||||||
|
* if something went initially wrong it may happen that
|
||||||
|
* there is just the version record. We try to fix it here.
|
||||||
|
* If we can't do that we return 0 - this is the version
|
||||||
|
* record and thus the actual read will detect the mismatch
|
||||||
|
* and bail out. Note that create_hashtable updates VR. */
|
||||||
|
take_write_lock ();
|
||||||
|
if (lseek (db_fd, 0, SEEK_END) == TRUST_RECORD_LEN)
|
||||||
|
create_hashtable (ctrl, &vr, 0);
|
||||||
|
release_write_lock ();
|
||||||
|
}
|
||||||
trusthashtbl = vr.r.ver.trusthashtbl;
|
trusthashtbl = vr.r.ver.trusthashtbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1269,6 +1308,13 @@ lookup_hashtable (ulong table, const byte *key, size_t keylen,
|
|||||||
int msb;
|
int msb;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
|
|
||||||
|
if (!table)
|
||||||
|
{
|
||||||
|
rc = gpg_error (GPG_ERR_INV_RECORD);
|
||||||
|
log_error("lookup_hashtable failed: %s\n", "request for record 0");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
hashrec = table;
|
hashrec = table;
|
||||||
next_level:
|
next_level:
|
||||||
msb = key[level];
|
msb = key[level];
|
||||||
@ -1358,7 +1404,7 @@ lookup_hashtable (ulong table, const byte *key, size_t keylen,
|
|||||||
static int
|
static int
|
||||||
update_trusthashtbl (ctrl_t ctrl, TRUSTREC *tr)
|
update_trusthashtbl (ctrl_t ctrl, TRUSTREC *tr)
|
||||||
{
|
{
|
||||||
return upd_hashtable (ctrl, get_trusthashrec (),
|
return upd_hashtable (ctrl, get_trusthashrec (ctrl),
|
||||||
tr->r.trust.fingerprint, 20, tr->recnum);
|
tr->r.trust.fingerprint, 20, tr->recnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1441,7 +1487,7 @@ tdbio_dump_record (TRUSTREC *rec, estream_t fp)
|
|||||||
* EXPECTED is not 0 reading any other record type will return an
|
* EXPECTED is not 0 reading any other record type will return an
|
||||||
* error.
|
* error.
|
||||||
*
|
*
|
||||||
* Return: 0 on success, -1 on EOF, or an error code.
|
* Return: 0 on success or an error code.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
tdbio_read_record (ulong recnum, TRUSTREC *rec, int expected)
|
tdbio_read_record (ulong recnum, TRUSTREC *rec, int expected)
|
||||||
@ -1466,7 +1512,7 @@ tdbio_read_record (ulong recnum, TRUSTREC *rec, int expected)
|
|||||||
n = read (db_fd, readbuf, TRUST_RECORD_LEN);
|
n = read (db_fd, readbuf, TRUST_RECORD_LEN);
|
||||||
if (!n)
|
if (!n)
|
||||||
{
|
{
|
||||||
return -1; /* eof */
|
return gpg_error (GPG_ERR_EOF);
|
||||||
}
|
}
|
||||||
else if (n != TRUST_RECORD_LEN)
|
else if (n != TRUST_RECORD_LEN)
|
||||||
{
|
{
|
||||||
@ -1700,7 +1746,7 @@ tdbio_delete_record (ctrl_t ctrl, ulong recnum)
|
|||||||
;
|
;
|
||||||
else if (rec.rectype == RECTYPE_TRUST)
|
else if (rec.rectype == RECTYPE_TRUST)
|
||||||
{
|
{
|
||||||
rc = drop_from_hashtable (ctrl, get_trusthashrec(),
|
rc = drop_from_hashtable (ctrl, get_trusthashrec (ctrl),
|
||||||
rec.r.trust.fingerprint, 20, rec.recnum);
|
rec.r.trust.fingerprint, 20, rec.recnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1746,20 +1792,14 @@ tdbio_new_recnum (ctrl_t ctrl)
|
|||||||
recnum = vr.r.ver.firstfree;
|
recnum = vr.r.ver.firstfree;
|
||||||
rc = tdbio_read_record (recnum, &rec, RECTYPE_FREE);
|
rc = tdbio_read_record (recnum, &rec, RECTYPE_FREE);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
log_fatal (_("%s: error reading free record: %s\n"),
|
||||||
log_error (_("%s: error reading free record: %s\n"),
|
|
||||||
db_name, gpg_strerror (rc));
|
db_name, gpg_strerror (rc));
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
/* Update dir record. */
|
/* Update dir record. */
|
||||||
vr.r.ver.firstfree = rec.r.free.next;
|
vr.r.ver.firstfree = rec.r.free.next;
|
||||||
rc = tdbio_write_record (ctrl, &vr);
|
rc = tdbio_write_record (ctrl, &vr);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
log_fatal (_("%s: error writing dir record: %s\n"),
|
||||||
log_error (_("%s: error writing dir record: %s\n"),
|
|
||||||
db_name, gpg_strerror (rc));
|
db_name, gpg_strerror (rc));
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
/* Zero out the new record. */
|
/* Zero out the new record. */
|
||||||
memset (&rec, 0, sizeof rec);
|
memset (&rec, 0, sizeof rec);
|
||||||
rec.rectype = 0; /* Mark as unused record (actually already done
|
rec.rectype = 0; /* Mark as unused record (actually already done
|
||||||
@ -1776,7 +1816,7 @@ tdbio_new_recnum (ctrl_t ctrl)
|
|||||||
if (offset == (off_t)(-1))
|
if (offset == (off_t)(-1))
|
||||||
log_fatal ("trustdb: lseek to end failed: %s\n", strerror (errno));
|
log_fatal ("trustdb: lseek to end failed: %s\n", strerror (errno));
|
||||||
recnum = offset / TRUST_RECORD_LEN;
|
recnum = offset / TRUST_RECORD_LEN;
|
||||||
log_assert (recnum); /* this is will never be the first record */
|
log_assert (recnum); /* This will never be the first record */
|
||||||
/* We must write a record, so that the next call to this
|
/* We must write a record, so that the next call to this
|
||||||
* function returns another recnum. */
|
* function returns another recnum. */
|
||||||
memset (&rec, 0, sizeof rec);
|
memset (&rec, 0, sizeof rec);
|
||||||
@ -1798,7 +1838,7 @@ tdbio_new_recnum (ctrl_t ctrl)
|
|||||||
{
|
{
|
||||||
rc = gpg_error_from_syserror ();
|
rc = gpg_error_from_syserror ();
|
||||||
log_error (_("trustdb rec %lu: write failed (n=%d): %s\n"),
|
log_error (_("trustdb rec %lu: write failed (n=%d): %s\n"),
|
||||||
recnum, n, strerror (errno));
|
recnum, n, gpg_strerror (rc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1828,12 +1868,12 @@ cmp_trec_fpr ( const void *fpr, const TRUSTREC *rec )
|
|||||||
* Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
|
* Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
tdbio_search_trust_byfpr (const byte *fingerprint, TRUSTREC *rec)
|
tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fingerprint, TRUSTREC *rec)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Locate the trust record using the hash table */
|
/* Locate the trust record using the hash table */
|
||||||
rc = lookup_hashtable (get_trusthashrec(), fingerprint, 20,
|
rc = lookup_hashtable (get_trusthashrec (ctrl), fingerprint, 20,
|
||||||
cmp_trec_fpr, fingerprint, rec );
|
cmp_trec_fpr, fingerprint, rec );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1846,7 +1886,7 @@ tdbio_search_trust_byfpr (const byte *fingerprint, TRUSTREC *rec)
|
|||||||
* Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
|
* Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
|
tdbio_search_trust_bypk (ctrl_t ctrl, PKT_public_key *pk, TRUSTREC *rec)
|
||||||
{
|
{
|
||||||
byte fingerprint[MAX_FINGERPRINT_LEN];
|
byte fingerprint[MAX_FINGERPRINT_LEN];
|
||||||
size_t fingerlen;
|
size_t fingerlen;
|
||||||
@ -1854,7 +1894,7 @@ tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
|
|||||||
fingerprint_from_pk( pk, fingerprint, &fingerlen );
|
fingerprint_from_pk( pk, fingerprint, &fingerlen );
|
||||||
for (; fingerlen < 20; fingerlen++)
|
for (; fingerlen < 20; fingerlen++)
|
||||||
fingerprint[fingerlen] = 0;
|
fingerprint[fingerlen] = 0;
|
||||||
return tdbio_search_trust_byfpr (fingerprint, rec);
|
return tdbio_search_trust_byfpr (ctrl, fingerprint, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,8 +110,10 @@ int tdbio_end_transaction(void);
|
|||||||
int tdbio_cancel_transaction(void);
|
int tdbio_cancel_transaction(void);
|
||||||
int tdbio_delete_record (ctrl_t ctrl, ulong recnum);
|
int tdbio_delete_record (ctrl_t ctrl, ulong recnum);
|
||||||
ulong tdbio_new_recnum (ctrl_t ctrl);
|
ulong tdbio_new_recnum (ctrl_t ctrl);
|
||||||
gpg_error_t tdbio_search_trust_byfpr (const byte *fingerprint, TRUSTREC *rec);
|
gpg_error_t tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fingerprint,
|
||||||
gpg_error_t tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec);
|
TRUSTREC *rec);
|
||||||
|
gpg_error_t tdbio_search_trust_bypk (ctrl_t ctrl, PKT_public_key *pk,
|
||||||
|
TRUSTREC *rec);
|
||||||
|
|
||||||
void tdbio_how_to_fix (void);
|
void tdbio_how_to_fix (void);
|
||||||
void tdbio_invalid(void);
|
void tdbio_invalid(void);
|
||||||
|
@ -649,7 +649,7 @@ read_trust_record (ctrl_t ctrl, PKT_public_key *pk, TRUSTREC *rec)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
init_trustdb (ctrl, 0);
|
init_trustdb (ctrl, 0);
|
||||||
rc = tdbio_search_trust_bypk (pk, rec);
|
rc = tdbio_search_trust_bypk (ctrl, pk, rec);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
|
if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
|
||||||
|
54
scd/apdu.c
54
scd/apdu.c
@ -119,6 +119,7 @@ struct reader_table_s {
|
|||||||
pcsc_dword_t modify_ioctl;
|
pcsc_dword_t modify_ioctl;
|
||||||
int pinmin;
|
int pinmin;
|
||||||
int pinmax;
|
int pinmax;
|
||||||
|
pcsc_dword_t current_state;
|
||||||
} pcsc;
|
} pcsc;
|
||||||
#ifdef USE_G10CODE_RAPDU
|
#ifdef USE_G10CODE_RAPDU
|
||||||
struct {
|
struct {
|
||||||
@ -228,6 +229,7 @@ static npth_mutex_t reader_table_lock;
|
|||||||
#define PCSC_E_READER_UNAVAILABLE 0x80100017
|
#define PCSC_E_READER_UNAVAILABLE 0x80100017
|
||||||
#define PCSC_E_NO_SERVICE 0x8010001D
|
#define PCSC_E_NO_SERVICE 0x8010001D
|
||||||
#define PCSC_E_SERVICE_STOPPED 0x8010001E
|
#define PCSC_E_SERVICE_STOPPED 0x8010001E
|
||||||
|
#define PCSC_W_RESET_CARD 0x80100068
|
||||||
#define PCSC_W_REMOVED_CARD 0x80100069
|
#define PCSC_W_REMOVED_CARD 0x80100069
|
||||||
|
|
||||||
/* Fix pcsc-lite ABI incompatibility. */
|
/* Fix pcsc-lite ABI incompatibility. */
|
||||||
@ -453,6 +455,7 @@ new_reader_slot (void)
|
|||||||
reader_table[reader].pcsc.modify_ioctl = 0;
|
reader_table[reader].pcsc.modify_ioctl = 0;
|
||||||
reader_table[reader].pcsc.pinmin = -1;
|
reader_table[reader].pcsc.pinmin = -1;
|
||||||
reader_table[reader].pcsc.pinmax = -1;
|
reader_table[reader].pcsc.pinmax = -1;
|
||||||
|
reader_table[reader].pcsc.current_state = PCSC_STATE_UNAWARE;
|
||||||
|
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
@ -653,12 +656,12 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire)
|
|||||||
(void)on_wire;
|
(void)on_wire;
|
||||||
memset (rdrstates, 0, sizeof *rdrstates);
|
memset (rdrstates, 0, sizeof *rdrstates);
|
||||||
rdrstates[0].reader = reader_table[slot].rdrname;
|
rdrstates[0].reader = reader_table[slot].rdrname;
|
||||||
rdrstates[0].current_state = PCSC_STATE_UNAWARE;
|
rdrstates[0].current_state = reader_table[slot].pcsc.current_state;
|
||||||
err = pcsc_get_status_change (reader_table[slot].pcsc.context,
|
err = pcsc_get_status_change (reader_table[slot].pcsc.context,
|
||||||
0,
|
0,
|
||||||
rdrstates, 1);
|
rdrstates, 1);
|
||||||
if (err == PCSC_E_TIMEOUT)
|
if (err == PCSC_E_TIMEOUT)
|
||||||
err = 0; /* Timeout is no error error here. */
|
err = 0; /* Timeout is no error here. */
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error ("pcsc_get_status_change failed: %s (0x%lx)\n",
|
log_error ("pcsc_get_status_change failed: %s (0x%lx)\n",
|
||||||
@ -666,24 +669,29 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire)
|
|||||||
return pcsc_error_to_sw (err);
|
return pcsc_error_to_sw (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* log_debug */
|
if ((rdrstates[0].event_state & PCSC_STATE_CHANGED))
|
||||||
/* ("pcsc_get_status_change: %s%s%s%s%s%s%s%s%s%s\n", */
|
reader_table[slot].pcsc.current_state =
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_IGNORE)? " ignore":"", */
|
(rdrstates[0].event_state & ~PCSC_STATE_CHANGED);
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_CHANGED)? " changed":"", */
|
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_UNKNOWN)? " unknown":"", */
|
if (DBG_CARD_IO)
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_UNAVAILABLE)?" unavail":"", */
|
log_debug
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_EMPTY)? " empty":"", */
|
("pcsc_get_status_change: %s%s%s%s%s%s%s%s%s%s\n",
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_PRESENT)? " present":"", */
|
(rdrstates[0].event_state & PCSC_STATE_IGNORE)? " ignore":"",
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_ATRMATCH)? " atr":"", */
|
(rdrstates[0].event_state & PCSC_STATE_CHANGED)? " changed":"",
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_EXCLUSIVE)? " excl":"", */
|
(rdrstates[0].event_state & PCSC_STATE_UNKNOWN)? " unknown":"",
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_INUSE)? " unuse":"", */
|
(rdrstates[0].event_state & PCSC_STATE_UNAVAILABLE)?" unavail":"",
|
||||||
/* (rdrstates[0].event_state & PCSC_STATE_MUTE)? " mute":"" ); */
|
(rdrstates[0].event_state & PCSC_STATE_EMPTY)? " empty":"",
|
||||||
|
(rdrstates[0].event_state & PCSC_STATE_PRESENT)? " present":"",
|
||||||
|
(rdrstates[0].event_state & PCSC_STATE_ATRMATCH)? " atr":"",
|
||||||
|
(rdrstates[0].event_state & PCSC_STATE_EXCLUSIVE)? " excl":"",
|
||||||
|
(rdrstates[0].event_state & PCSC_STATE_INUSE)? " inuse":"",
|
||||||
|
(rdrstates[0].event_state & PCSC_STATE_MUTE)? " mute":"" );
|
||||||
|
|
||||||
*status = 0;
|
*status = 0;
|
||||||
if ( (rdrstates[0].event_state & PCSC_STATE_PRESENT) )
|
if ( (reader_table[slot].pcsc.current_state & PCSC_STATE_PRESENT) )
|
||||||
{
|
{
|
||||||
*status |= APDU_CARD_PRESENT;
|
*status |= APDU_CARD_PRESENT;
|
||||||
if ( !(rdrstates[0].event_state & PCSC_STATE_MUTE) )
|
if ( !(reader_table[slot].pcsc.current_state & PCSC_STATE_MUTE) )
|
||||||
*status |= APDU_CARD_ACTIVE;
|
*status |= APDU_CARD_ACTIVE;
|
||||||
}
|
}
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
@ -692,7 +700,7 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire)
|
|||||||
mode. */
|
mode. */
|
||||||
if ( (*status & (APDU_CARD_PRESENT|APDU_CARD_ACTIVE))
|
if ( (*status & (APDU_CARD_PRESENT|APDU_CARD_ACTIVE))
|
||||||
== (APDU_CARD_PRESENT|APDU_CARD_ACTIVE)
|
== (APDU_CARD_PRESENT|APDU_CARD_ACTIVE)
|
||||||
&& !(rdrstates[0].event_state & PCSC_STATE_INUSE) )
|
&& !(reader_table[slot].pcsc.current_state & PCSC_STATE_INUSE) )
|
||||||
*status |= APDU_CARD_USABLE;
|
*status |= APDU_CARD_USABLE;
|
||||||
#else
|
#else
|
||||||
/* Some winscard drivers may set EXCLUSIVE and INUSE at the same
|
/* Some winscard drivers may set EXCLUSIVE and INUSE at the same
|
||||||
@ -702,6 +710,10 @@ pcsc_get_status (int slot, unsigned int *status, int on_wire)
|
|||||||
*status |= APDU_CARD_USABLE;
|
*status |= APDU_CARD_USABLE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!on_wire && (rdrstates[0].event_state & PCSC_STATE_CHANGED))
|
||||||
|
/* Event like sleep/resume occurs, which requires RESET. */
|
||||||
|
return SW_HOST_NO_READER;
|
||||||
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,6 +753,14 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
|||||||
log_error ("pcsc_transmit failed: %s (0x%lx)\n",
|
log_error ("pcsc_transmit failed: %s (0x%lx)\n",
|
||||||
pcsc_error_string (err), err);
|
pcsc_error_string (err), err);
|
||||||
|
|
||||||
|
/* Handle fatal errors which require shutdown of reader. */
|
||||||
|
if (err == PCSC_E_NOT_TRANSACTED || err == PCSC_W_RESET_CARD
|
||||||
|
|| err == PCSC_W_REMOVED_CARD)
|
||||||
|
{
|
||||||
|
reader_table[slot].pcsc.current_state = PCSC_STATE_UNAWARE;
|
||||||
|
scd_kick_the_loop ();
|
||||||
|
}
|
||||||
|
|
||||||
return pcsc_error_to_sw (err);
|
return pcsc_error_to_sw (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,7 +1018,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
|||||||
|
|
||||||
snprintf (tmp, sizeof tmp,
|
snprintf (tmp, sizeof tmp,
|
||||||
"gc=%d ki=%d fc=%d pd=%d mcl3=%u aac=%d "
|
"gc=%d ki=%d fc=%d pd=%d mcl3=%u aac=%d "
|
||||||
"sm=%d si=%u dec=%d bt=%d",
|
"sm=%d si=%u dec=%d bt=%d kdf=%d",
|
||||||
app->app_local->extcap.get_challenge,
|
app->app_local->extcap.get_challenge,
|
||||||
app->app_local->extcap.key_import,
|
app->app_local->extcap.key_import,
|
||||||
app->app_local->extcap.change_force_chv,
|
app->app_local->extcap.change_force_chv,
|
||||||
@ -1032,7 +1032,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
|||||||
: 0),
|
: 0),
|
||||||
app->app_local->status_indicator,
|
app->app_local->status_indicator,
|
||||||
app->app_local->extcap.has_decrypt,
|
app->app_local->extcap.has_decrypt,
|
||||||
app->app_local->extcap.has_button);
|
app->app_local->extcap.has_button,
|
||||||
|
app->app_local->extcap.kdf_do);
|
||||||
send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
|
send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1467,7 +1467,8 @@ intr_cb (struct libusb_transfer *transfer)
|
|||||||
|
|
||||||
DEBUGOUT_1 ("CCID: interrupt callback %d\n", transfer->status);
|
DEBUGOUT_1 ("CCID: interrupt callback %d\n", transfer->status);
|
||||||
|
|
||||||
if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT)
|
if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT
|
||||||
|
|| transfer->status == LIBUSB_TRANSFER_NO_DEVICE)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -393,7 +393,21 @@ cleanup (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_signal_mask (void)
|
||||||
|
{
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
npth_sigev_init ();
|
||||||
|
npth_sigev_add (SIGHUP);
|
||||||
|
npth_sigev_add (SIGUSR1);
|
||||||
|
npth_sigev_add (SIGUSR2);
|
||||||
|
npth_sigev_add (SIGINT);
|
||||||
|
npth_sigev_add (SIGCONT);
|
||||||
|
npth_sigev_add (SIGTERM);
|
||||||
|
npth_sigev_fini ();
|
||||||
|
main_thread_pid = getpid ();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv )
|
main (int argc, char **argv )
|
||||||
@ -744,6 +758,7 @@ main (int argc, char **argv )
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
npth_init ();
|
npth_init ();
|
||||||
|
setup_signal_mask ();
|
||||||
gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
|
gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
|
||||||
|
|
||||||
/* If --debug-allow-core-dump has been given we also need to
|
/* If --debug-allow-core-dump has been given we also need to
|
||||||
@ -884,6 +899,7 @@ main (int argc, char **argv )
|
|||||||
/* This is the child. */
|
/* This is the child. */
|
||||||
|
|
||||||
npth_init ();
|
npth_init ();
|
||||||
|
setup_signal_mask ();
|
||||||
gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
|
gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
|
||||||
|
|
||||||
/* Detach from tty and put process into a new session. */
|
/* Detach from tty and put process into a new session. */
|
||||||
@ -1206,18 +1222,16 @@ start_connection_thread (void *arg)
|
|||||||
void
|
void
|
||||||
scd_kick_the_loop (void)
|
scd_kick_the_loop (void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Kick the select loop. */
|
/* Kick the select loop. */
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
ret = SetEvent (the_event);
|
int ret = SetEvent (the_event);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
log_error ("SetEvent for scd_kick_the_loop failed: %s\n",
|
log_error ("SetEvent for scd_kick_the_loop failed: %s\n",
|
||||||
w32_strerror (-1));
|
w32_strerror (-1));
|
||||||
#elif defined(HAVE_PSELECT_NO_EINTR)
|
#elif defined(HAVE_PSELECT_NO_EINTR)
|
||||||
write (notify_fd, "", 1);
|
write (notify_fd, "", 1);
|
||||||
#else
|
#else
|
||||||
ret = kill (main_thread_pid, SIGCONT);
|
int ret = kill (main_thread_pid, SIGCONT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
log_error ("SetEvent for scd_kick_the_loop failed: %s\n",
|
log_error ("SetEvent for scd_kick_the_loop failed: %s\n",
|
||||||
gpg_strerror (gpg_error_from_syserror ()));
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
@ -1292,16 +1306,6 @@ handle_connections (int listen_fd)
|
|||||||
events[0] = the_event = h2;
|
events[0] = the_event = h2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
npth_sigev_init ();
|
|
||||||
npth_sigev_add (SIGHUP);
|
|
||||||
npth_sigev_add (SIGUSR1);
|
|
||||||
npth_sigev_add (SIGUSR2);
|
|
||||||
npth_sigev_add (SIGINT);
|
|
||||||
npth_sigev_add (SIGCONT);
|
|
||||||
npth_sigev_add (SIGTERM);
|
|
||||||
npth_sigev_fini ();
|
|
||||||
main_thread_pid = getpid ();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FD_ZERO (&fdset);
|
FD_ZERO (&fdset);
|
||||||
@ -1348,6 +1352,8 @@ handle_connections (int listen_fd)
|
|||||||
FD_SET (pipe_fd[0], &read_fdset);
|
FD_SET (pipe_fd[0], &read_fdset);
|
||||||
if (max_fd < pipe_fd[0])
|
if (max_fd < pipe_fd[0])
|
||||||
max_fd = pipe_fd[0];
|
max_fd = pipe_fd[0];
|
||||||
|
#else
|
||||||
|
(void)max_fd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
@ -179,6 +179,20 @@ start_agent (ctrl_t ctrl)
|
|||||||
gpg_strerror (rc));
|
gpg_strerror (rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pass on the request origin. */
|
||||||
|
if (opt.request_origin)
|
||||||
|
{
|
||||||
|
char *tmp = xasprintf ("OPTION pretend-request-origin=%s",
|
||||||
|
str_request_origin (opt.request_origin));
|
||||||
|
rc = assuan_transact (agent_ctx, tmp,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
xfree (tmp);
|
||||||
|
if (rc)
|
||||||
|
log_error ("setting request origin '%s' failed: %s\n",
|
||||||
|
str_request_origin (opt.request_origin),
|
||||||
|
gpg_strerror (rc));
|
||||||
|
}
|
||||||
|
|
||||||
/* In DE_VS mode under Windows we require that the JENT RNG
|
/* In DE_VS mode under Windows we require that the JENT RNG
|
||||||
* is active. */
|
* is active. */
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
@ -125,6 +125,7 @@ enum cmd_and_opt_values {
|
|||||||
|
|
||||||
oPassphraseFD,
|
oPassphraseFD,
|
||||||
oPinentryMode,
|
oPinentryMode,
|
||||||
|
oRequestOrigin,
|
||||||
|
|
||||||
oAssumeArmor,
|
oAssumeArmor,
|
||||||
oAssumeBase64,
|
oAssumeBase64,
|
||||||
@ -255,6 +256,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
|
|
||||||
ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"),
|
ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"),
|
||||||
ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"),
|
ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"),
|
||||||
|
ARGPARSE_s_s (oRequestOrigin, "request-origin", "@"),
|
||||||
|
|
||||||
ARGPARSE_s_n (oAssumeArmor, "assume-armor",
|
ARGPARSE_s_n (oAssumeArmor, "assume-armor",
|
||||||
N_("assume input is in PEM format")),
|
N_("assume input is in PEM format")),
|
||||||
@ -1162,6 +1164,12 @@ main ( int argc, char **argv)
|
|||||||
log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
|
log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oRequestOrigin:
|
||||||
|
opt.request_origin = parse_request_origin (pargs.r.ret_str);
|
||||||
|
if (opt.request_origin == -1)
|
||||||
|
log_error (_("invalid request origin '%s'\n"), pargs.r.ret_str);
|
||||||
|
break;
|
||||||
|
|
||||||
/* Input encoding selection. */
|
/* Input encoding selection. */
|
||||||
case oAssumeArmor:
|
case oAssumeArmor:
|
||||||
ctrl.autodetect_encoding = 0;
|
ctrl.autodetect_encoding = 0;
|
||||||
|
@ -88,6 +88,7 @@ struct
|
|||||||
int with_key_screening; /* Option --with-key-screening active. */
|
int with_key_screening; /* Option --with-key-screening active. */
|
||||||
|
|
||||||
int pinentry_mode;
|
int pinentry_mode;
|
||||||
|
int request_origin;
|
||||||
|
|
||||||
int armor; /* force base64 armoring (see also ctrl.with_base64) */
|
int armor; /* force base64 armoring (see also ctrl.with_base64) */
|
||||||
int no_armor; /* don't try to figure out whether data is base64 armored*/
|
int no_armor; /* don't try to figure out whether data is base64 armored*/
|
||||||
|
12
sm/server.c
12
sm/server.c
@ -32,6 +32,7 @@
|
|||||||
#include "../common/sysutils.h"
|
#include "../common/sysutils.h"
|
||||||
#include "../common/server-help.h"
|
#include "../common/server-help.h"
|
||||||
#include "../common/asshelp.h"
|
#include "../common/asshelp.h"
|
||||||
|
#include "../common/shareddefs.h"
|
||||||
|
|
||||||
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
|
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
|
||||||
|
|
||||||
@ -289,6 +290,17 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
|
|||||||
ctrl->offline = i;
|
ctrl->offline = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!strcmp (key, "request-origin"))
|
||||||
|
{
|
||||||
|
if (!opt.request_origin)
|
||||||
|
{
|
||||||
|
int i = parse_request_origin (value);
|
||||||
|
if (i == -1)
|
||||||
|
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
else
|
||||||
|
opt.request_origin = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
|
err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user