Codebase list gpgme1.0 / 34d9def
core: Allow specifying an expiration date for key signatures * src/context.h (struct gpgme_context): Add 'cert_expire'. * src/engine-gpg.c (append_args_from_cert_expire): New. (gpg_edit): Set option according to the new flag. * src/gpgme.c (gpgme_release): Free 'cert_expire'. (gpgme_set_ctx_flag, gpgme_get_ctx_flag): Add "cert-expire". * tests/gpg/Makefile.am (c_tests): Add new test. (gpg.conf): Write "allow-weak-key-signatures" to gpg.conf. * tests/gpg/t-edit-sign.c: New. -- The new context flag "cert-expire" allows setting the expiration date for key signatures created with gpgme_op_interact. GnuPG-bug-id: 5336, 5505 Ingo Klöcker 2 years ago
7 changed file(s) with 253 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
00 Noteworthy changes in version 1.15.2 (unreleased)
11 -------------------------------------------------
22
3 * New context flag "cert-expire".
4
35 * cpp, qt: Add support for trust signatures. [#5421]
46
57 * qt: Add support for flags in LDAP server options. [#5217]
68
79 * Interface changes relative to the 1.15.1 release:
810 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 gpgme_set_ctx_flag EXTENDED: New flag 'cert-expire'.
912 cpp: SignKeyJob::setTrustSignature NEW.
1013 cpp: TrustSignatureTrust NEW.
1114 cpp: GpgSignKeyEditInteractor::setTrustSignatureTrust NEW.
31783178 This flag passes the option @option{--expert} to gpg key edit. This
31793179 can be used to get additional callbacks in @code{gpgme_op_edit}.
31803180
3181 @item "cert-expire"
3182 @since{1.15.2}
3183 The string given in @var{value} is passed to the GnuPG engine to set
3184 the expiration time to use for key signature expiration. Valid values
3185 are documented in the GnuPG manual and the gpg man page under
3186 the option @option{--default-cert-expire}.
3187
3188
31813189 @end table
31823190
31833191 This function returns @code{0} on success.
173173 /* The optional trust-model override. */
174174 char *trust_model;
175175
176 /* The optional expiration date of a certification. */
177 char *cert_expire;
178
176179 /* The operation data hooked into the context. */
177180 ctx_op_data_t op_data;
178181
19601960
19611961
19621962 static gpgme_error_t
1963 append_args_from_cert_expire (engine_gpg_t gpg, gpgme_ctx_t ctx)
1964 {
1965 gpgme_error_t err;
1966
1967 if (ctx->cert_expire)
1968 {
1969 /* Override ask-cert-expire set in the configuration, so that the specified
1970 * default is actually used. */
1971 err = add_arg (gpg, "--no-ask-cert-expire");
1972 if (!err)
1973 err = add_arg (gpg, "--default-cert-expire");
1974 if (!err)
1975 err = add_arg (gpg, ctx->cert_expire);
1976 }
1977 else
1978 err = 0;
1979 return err;
1980 }
1981
1982
1983 static gpgme_error_t
19631984 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
19641985 gpgme_ctx_t ctx /* FIXME */)
19651986 {
19741995 err = append_args_from_signers (gpg, ctx);
19751996 if (!err)
19761997 err = append_args_from_sig_notations (gpg, ctx, NOTATION_FLAG_CERT);
1998 if (!err)
1999 err = append_args_from_cert_expire (gpg, ctx);
19772000 if (!err)
19782001 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
19792002 if (!err)
252252 free (ctx->request_origin);
253253 free (ctx->auto_key_locate);
254254 free (ctx->trust_model);
255 free (ctx->cert_expire);
255256 _gpgme_engine_info_release (ctx->engine_info);
256257 ctx->engine_info = NULL;
257258 DESTROY_LOCK (ctx->lock);
577578 {
578579 ctx->extended_edit = abool;
579580 }
581 else if (!strcmp (name, "cert-expire"))
582 {
583 free (ctx->cert_expire);
584 ctx->cert_expire = strdup (value);
585 if (!ctx->cert_expire)
586 err = gpg_error_from_syserror ();
587 }
580588 else
581589 err = gpg_error (GPG_ERR_UNKNOWN_NAME);
582590
645653 else if (!strcmp (name, "extended-edit"))
646654 {
647655 return ctx->extended_edit ? "1":"";
656 }
657 else if (!strcmp (name, "cert-expire"))
658 {
659 return ctx->cert_expire? ctx->cert_expire : "";
648660 }
649661 else
650662 return NULL;
3838 t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
3939 t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
4040 t-import t-edit t-keylist t-keylist-sig t-keylist-secret-sig t-wait \
41 t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed \
41 t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed t-edit-sign \
4242 $(tests_unix)
4343
4444 TESTS = initial.test $(c_tests) final.test
103103 gpg.conf:
104104 # This is required for t-sig-notations.
105105 echo no-force-v3-sigs > ./gpg.conf
106 # This is required for t-edit-sign.
107 echo allow-weak-key-signatures >> ./gpg.conf
106108
107109 gpg-agent.conf:
108110 # This is required for gpg2, which does not support command fd for the
0 /* t-edit-sign.c - Regression test.
1 * Copyright (C) 2000 Werner Koch (dd9jn)
2 * Copyright (C) 2001, 2002, 2003, 2004, 2021 g10 Code GmbH
3 * Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
4 *
5 * This file is part of GPGME.
6 *
7 * GPGME is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * GPGME is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, see <https://gnu.org/licenses/>.
19 * SPDX-License-Identifier: LGPL-2.1-or-later
20 */
21
22 /* We need to include config.h so that we know whether we are building
23 with large file system (LFS) support. */
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <errno.h>
35
36 #include <gpgme.h>
37
38 #include "t-support.h"
39
40
41 static void
42 flush_data (gpgme_data_t dh)
43 {
44 char buf[100];
45 int ret;
46
47 ret = gpgme_data_seek (dh, 0, SEEK_SET);
48 if (ret)
49 fail_if_err (gpgme_error_from_errno (errno));
50 while ((ret = gpgme_data_read (dh, buf, 100)) > 0)
51 fwrite (buf, ret, 1, stdout);
52 if (ret < 0)
53 fail_if_err (gpgme_error_from_errno (errno));
54 }
55
56
57 gpgme_error_t
58 interact_fnc (void *opaque, const char *status, const char *args, int fd)
59 {
60 const char *result = NULL;
61 gpgme_data_t out = (gpgme_data_t) opaque;
62
63 fputs ("[-- Response --]\n", stdout);
64 flush_data (out);
65
66 fprintf (stdout, "[-- Code: %s, %s --]\n", status, args);
67
68 if (fd >= 0)
69 {
70 if (!strcmp (args, "keyedit.prompt"))
71 {
72 static int step = 0;
73
74 switch (step)
75 {
76 case 0:
77 result = "fpr";
78 break;
79 case 1:
80 /* This fixes the primary user ID so the keylisting
81 tests will have predictable output. */
82 result = "1";
83 break;
84 case 2:
85 result = "sign";
86 break;
87
88 default:
89 result = "quit";
90 break;
91 }
92 step++;
93 }
94 else if (!strcmp (args, "keyedit.save.okay"))
95 result = "Y";
96 else if (!strcmp (args, "sign_uid.okay"))
97 result = "Y";
98 }
99
100 if (result)
101 {
102 gpgme_io_writen (fd, result, strlen (result));
103 gpgme_io_writen (fd, "\n", 1);
104 }
105 return 0;
106 }
107
108
109 int
110 main (int argc, char **argv)
111 {
112 gpgme_ctx_t ctx;
113 gpgme_error_t err;
114 gpgme_data_t out = NULL;
115 const char *signer_fpr = "A0FF4590BB6122EDEF6E3C542D727CC768697734"; /* Alpha Test */
116 gpgme_key_t signing_key = NULL;
117 const char *key_fpr = "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2"; /* Bravo Test */
118 gpgme_key_t key = NULL;
119 gpgme_key_t signed_key = NULL;
120 gpgme_user_id_t signed_uid = NULL;
121 gpgme_key_sig_t key_sig = NULL;
122 char *agent_info;
123 int mode;
124
125 (void)argc;
126 (void)argv;
127
128 init_gpgme (GPGME_PROTOCOL_OpenPGP);
129
130 err = gpgme_new (&ctx);
131 fail_if_err (err);
132
133 /* Sign the key */
134 agent_info = getenv("GPG_AGENT_INFO");
135 if (!(agent_info && strchr (agent_info, ':')))
136 gpgme_set_passphrase_cb (ctx, passphrase_cb, 0);
137
138 err = gpgme_get_key (ctx, signer_fpr, &signing_key, 1);
139 fail_if_err (err);
140 err = gpgme_signers_add (ctx, signing_key);
141 fail_if_err (err);
142
143 err = gpgme_set_ctx_flag (ctx, "cert-expire", "42d");
144 fail_if_err (err);
145
146 err = gpgme_get_key (ctx, key_fpr, &key, 0);
147 fail_if_err (err);
148
149 err = gpgme_data_new (&out);
150 fail_if_err (err);
151
152 err = gpgme_op_interact (ctx, key, 0, interact_fnc, out, out);
153 fail_if_err (err);
154
155 fputs ("[-- Last response --]\n", stdout);
156 flush_data (out);
157
158 gpgme_data_release (out);
159 gpgme_key_unref (key);
160 gpgme_key_unref (signing_key);
161
162 /* Verify the key signature */
163 mode = gpgme_get_keylist_mode (ctx);
164 mode |= GPGME_KEYLIST_MODE_SIGS;
165 err = gpgme_set_keylist_mode (ctx, mode);
166 fail_if_err (err);
167 err = gpgme_get_key (ctx, key_fpr, &signed_key, 0);
168 fail_if_err (err);
169
170 signed_uid = key->uids;
171 if (!signed_uid)
172 {
173 fprintf (stderr, "Signed key has no user IDs\n");
174 exit (1);
175 }
176 if (!signed_uid->signatures || !signed_uid->signatures->next)
177 {
178 fprintf (stderr, "Signed user ID has less signatures than expected\n");
179 exit (1);
180 }
181 key_sig = signed_uid->signatures->next;
182 if (strcmp ("2D727CC768697734", key_sig->keyid))
183 {
184 fprintf (stderr, "Unexpected key ID in second user ID sig: %s\n",
185 key_sig->keyid);
186 exit (1);
187 }
188 if (key_sig->expires != key_sig->timestamp + 42*86400L)
189 {
190 fprintf (stderr, "Key signature unexpectedly does not expire in 42 days\n");
191 fprintf (stderr, "signature date: %ld, expiration date: %ld\n",
192 key_sig->timestamp, key_sig->expires);
193 exit (1);
194 }
195
196 gpgme_key_unref (signed_key);
197 gpgme_release (ctx);
198
199 return 0;
200 }