Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F22067588
certreqgen-ui.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
13 KB
Subscribers
None
certreqgen-ui.c
View Options
/* certreqgen-ui.c - Simple user interface for certreqgen.c
* Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include
<config.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<errno.h>
#include
<unistd.h>
#include
<time.h>
#include
"gpgsm.h"
#include
<gcrypt.h>
#include
"../common/i18n.h"
#include
"../common/ttyio.h"
#include
"../common/membuf.h"
/* Prompt for lines and append them to MB. */
static
void
ask_mb_lines
(
membuf_t
*
mb
,
const
char
*
prefix
)
{
char
*
answer
=
NULL
;
do
{
xfree
(
answer
);
answer
=
tty_get
(
"> "
);
tty_kill_prompt
();
trim_spaces
(
answer
);
if
(
*
answer
)
{
put_membuf_str
(
mb
,
prefix
);
put_membuf_str
(
mb
,
answer
);
put_membuf
(
mb
,
"
\n
"
,
1
);
}
}
while
(
*
answer
);
xfree
(
answer
);
}
/* Helper to store stuff in a membuf. */
void
store_key_value_lf
(
membuf_t
*
mb
,
const
char
*
key
,
const
char
*
value
)
{
put_membuf_str
(
mb
,
key
);
put_membuf_str
(
mb
,
value
);
put_membuf
(
mb
,
"
\n
"
,
1
);
}
/* Helper tp store a membuf create by mb_ask_lines into MB. Returns
-1 on error. */
int
store_mb_lines
(
membuf_t
*
mb
,
membuf_t
*
lines
)
{
char
*
p
;
if
(
get_membuf_len
(
lines
))
{
put_membuf
(
lines
,
""
,
1
);
p
=
get_membuf
(
lines
,
NULL
);
if
(
!
p
)
return
-1
;
put_membuf_str
(
mb
,
p
);
xfree
(
p
);
}
return
0
;
}
/* Check whether we have a key for the key with HEXGRIP. Returns NULL
if not or a string describing the type of the key (RSA, ELG, DSA,
etc..). */
static
const
char
*
check_keygrip
(
ctrl_t
ctrl
,
const
char
*
hexgrip
)
{
gpg_error_t
err
;
ksba_sexp_t
public
;
size_t
publiclen
;
int
algo
;
if
(
hexgrip
[
0
]
==
'&'
)
hexgrip
++
;
err
=
gpgsm_agent_readkey
(
ctrl
,
0
,
hexgrip
,
&
public
);
if
(
err
)
return
NULL
;
publiclen
=
gcry_sexp_canon_len
(
public
,
0
,
NULL
,
NULL
);
algo
=
get_pk_algo_from_canon_sexp
(
public
,
publiclen
);
xfree
(
public
);
switch
(
algo
)
{
case
GCRY_PK_RSA
:
return
"RSA"
;
case
GCRY_PK_DSA
:
return
"DSA"
;
case
GCRY_PK_ELG
:
return
"ELG"
;
case
GCRY_PK_ECC
:
return
"ECC"
;
case
GCRY_PK_ECDSA
:
return
"ECDSA"
;
case
GCRY_PK_EDDSA
:
return
"EdDSA"
;
default
:
return
NULL
;
}
}
/* This function is used to create a certificate request from the
command line. In the past the similar gpgsm-gencert.sh script has
been used for it; however that scripts requires a full Unix shell
and thus is not suitable for the Windows port. So here is the
re-implementation. */
void
gpgsm_gencertreq_tty
(
ctrl_t
ctrl
,
estream_t
output_stream
)
{
gpg_error_t
err
;
char
*
answer
;
int
selection
;
estream_t
fp
=
NULL
;
int
method
;
char
*
keytype_buffer
=
NULL
;
const
char
*
keytype
;
char
*
keygrip
=
NULL
;
unsigned
int
nbits
;
int
minbits
=
1024
;
int
maxbits
=
4096
;
int
defbits
=
3072
;
const
char
*
keyusage
;
char
*
subject_name
;
membuf_t
mb_email
,
mb_dns
,
mb_uri
,
mb_result
;
char
*
result
=
NULL
;
const
char
*
s
,
*
s2
;
int
selfsigned
;
answer
=
NULL
;
init_membuf
(
&
mb_email
,
100
);
init_membuf
(
&
mb_dns
,
100
);
init_membuf
(
&
mb_uri
,
100
);
init_membuf
(
&
mb_result
,
512
);
again
:
/* Get the type of the key. */
tty_printf
(
_
(
"Please select what kind of key you want:
\n
"
));
tty_printf
(
_
(
" (%d) RSA
\n
"
),
1
);
tty_printf
(
_
(
" (%d) Existing key
\n
"
),
2
);
tty_printf
(
_
(
" (%d) Existing key from card
\n
"
),
3
);
do
{
xfree
(
answer
);
answer
=
tty_get
(
_
(
"Your selection? "
));
tty_kill_prompt
();
selection
=
*
answer
?
atoi
(
answer
)
:
1
;
}
while
(
!
(
selection
>=
1
&&
selection
<=
3
));
method
=
selection
;
/* Get size of the key. */
if
(
method
==
1
)
{
keytype
=
"RSA"
;
for
(;;)
{
xfree
(
answer
);
answer
=
tty_getf
(
_
(
"What keysize do you want? (%u) "
),
defbits
);
tty_kill_prompt
();
trim_spaces
(
answer
);
nbits
=
*
answer
?
atoi
(
answer
)
:
defbits
;
if
(
nbits
<
minbits
||
nbits
>
maxbits
)
tty_printf
(
_
(
"%s keysizes must be in the range %u-%u
\n
"
),
"RSA"
,
minbits
,
maxbits
);
else
break
;
/* Okay. */
}
tty_printf
(
_
(
"Requested keysize is %u bits
\n
"
),
nbits
);
/* We round it up so that it better matches the word size. */
if
((
nbits
%
64
))
{
nbits
=
((
nbits
+
63
)
/
64
)
*
64
;
tty_printf
(
_
(
"rounded up to %u bits
\n
"
),
nbits
);
}
}
else
if
(
method
==
2
)
{
for
(;;)
{
xfree
(
answer
);
answer
=
tty_get
(
_
(
"Enter the keygrip: "
));
tty_kill_prompt
();
trim_spaces
(
answer
);
if
(
!*
answer
)
goto
again
;
else
if
(
strlen
(
answer
)
!=
40
&&
!
(
answer
[
0
]
==
'&'
&&
strlen
(
answer
+
1
)
==
40
))
tty_printf
(
_
(
"Not a valid keygrip (expecting 40 hex digits)
\n
"
));
else
if
(
!
(
keytype
=
check_keygrip
(
ctrl
,
answer
))
)
tty_printf
(
_
(
"No key with this keygrip
\n
"
));
else
break
;
/* Okay. */
}
xfree
(
keygrip
);
keygrip
=
answer
;
answer
=
NULL
;
nbits
=
1024
;
/* A dummy value is sufficient. */
}
else
/* method == 3 */
{
char
*
serialno
;
strlist_t
keypairlist
,
sl
;
int
count
;
err
=
gpgsm_agent_scd_serialno
(
ctrl
,
&
serialno
);
if
(
err
)
{
tty_printf
(
_
(
"error reading the card: %s
\n
"
),
gpg_strerror
(
err
));
goto
again
;
}
tty_printf
(
_
(
"Serial number of the card: %s
\n
"
),
serialno
);
xfree
(
serialno
);
err
=
gpgsm_agent_scd_keypairinfo
(
ctrl
,
&
keypairlist
);
if
(
err
)
{
tty_printf
(
_
(
"error reading the card: %s
\n
"
),
gpg_strerror
(
err
));
goto
again
;
}
do
{
tty_printf
(
_
(
"Available keys:
\n
"
));
for
(
count
=
1
,
sl
=
keypairlist
;
sl
;
sl
=
sl
->
next
,
count
++
)
{
ksba_sexp_t
pkey
;
gcry_sexp_t
s_pkey
;
char
*
algostr
=
NULL
;
const
char
*
keyref
;
int
any
=
0
;
keyref
=
strchr
(
sl
->
d
,
' '
);
if
(
keyref
)
{
keyref
++
;
if
(
!
gpgsm_agent_readkey
(
ctrl
,
1
,
keyref
,
&
pkey
))
{
if
(
!
gcry_sexp_new
(
&
s_pkey
,
pkey
,
0
,
0
))
algostr
=
pubkey_algo_string
(
s_pkey
,
NULL
);
gcry_sexp_release
(
s_pkey
);
}
xfree
(
pkey
);
}
tty_printf
(
" (%d) %s %s"
,
count
,
sl
->
d
,
algostr
);
if
((
sl
->
flags
&
GCRY_PK_USAGE_CERT
))
{
tty_printf
(
"%scert"
,
any
?
","
:
" ("
);
any
=
1
;
}
if
((
sl
->
flags
&
GCRY_PK_USAGE_SIGN
))
{
tty_printf
(
"%ssign"
,
any
?
","
:
" ("
);
any
=
1
;
}
if
((
sl
->
flags
&
GCRY_PK_USAGE_AUTH
))
{
tty_printf
(
"%sauth"
,
any
?
","
:
" ("
);
any
=
1
;
}
if
((
sl
->
flags
&
GCRY_PK_USAGE_ENCR
))
{
tty_printf
(
"%sencr"
,
any
?
","
:
" ("
);
any
=
1
;
}
tty_printf
(
"%s
\n
"
,
any
?
")"
:
""
);
xfree
(
algostr
);
}
xfree
(
answer
);
answer
=
tty_get
(
_
(
"Your selection? "
));
tty_kill_prompt
();
trim_spaces
(
answer
);
selection
=
atoi
(
answer
);
}
while
(
!
(
selection
>
0
&&
selection
<
count
));
for
(
count
=
1
,
sl
=
keypairlist
;
sl
;
sl
=
sl
->
next
,
count
++
)
if
(
count
==
selection
)
break
;
s
=
sl
->
d
;
while
(
*
s
&&
!
spacep
(
s
))
s
++
;
while
(
spacep
(
s
))
s
++
;
xfree
(
keygrip
);
keygrip
=
NULL
;
xfree
(
keytype_buffer
);
keytype_buffer
=
xasprintf
(
"card:%s"
,
s
);
free_strlist
(
keypairlist
);
keytype
=
keytype_buffer
;
nbits
=
1024
;
/* A dummy value is sufficient. */
}
/* Ask for the key usage. */
tty_printf
(
_
(
"Possible actions for a %s key:
\n
"
),
"RSA"
);
tty_printf
(
_
(
" (%d) sign, encrypt
\n
"
),
1
);
tty_printf
(
_
(
" (%d) sign
\n
"
),
2
);
tty_printf
(
_
(
" (%d) encrypt
\n
"
),
3
);
do
{
xfree
(
answer
);
answer
=
tty_get
(
_
(
"Your selection? "
));
tty_kill_prompt
();
trim_spaces
(
answer
);
selection
=
*
answer
?
atoi
(
answer
)
:
1
;
switch
(
selection
)
{
case
1
:
keyusage
=
"sign, encrypt"
;
break
;
case
2
:
keyusage
=
"sign"
;
break
;
case
3
:
keyusage
=
"encrypt"
;
break
;
default
:
keyusage
=
NULL
;
break
;
}
}
while
(
!
keyusage
);
/* Get the subject name. */
do
{
size_t
erroff
,
errlen
;
xfree
(
answer
);
answer
=
tty_get
(
_
(
"Enter the X.509 subject name: "
));
tty_kill_prompt
();
trim_spaces
(
answer
);
if
(
!*
answer
)
tty_printf
(
_
(
"No subject name given
\n
"
));
else
if
(
(
err
=
ksba_dn_teststr
(
answer
,
0
,
&
erroff
,
&
errlen
))
)
{
if
(
gpg_err_code
(
err
)
==
GPG_ERR_UNKNOWN_NAME
)
tty_printf
(
_
(
"Invalid subject name label '%.*s'
\n
"
),
(
int
)
errlen
,
answer
+
erroff
);
else
{
/* TRANSLATORS: The 22 in the second string is the
length of the first string up to the "%s". Please
adjust it do the length of your translation. The
second string is merely passed to atoi so you can
drop everything after the number. */
tty_printf
(
_
(
"Invalid subject name '%s'
\n
"
),
answer
);
tty_printf
(
"%*s^
\n
"
,
atoi
(
_
(
"22 translator: see "
"certreg-ui.c:gpgsm_gencertreq_tty"
))
+
(
int
)
erroff
,
""
);
}
*
answer
=
0
;
}
}
while
(
!*
answer
);
subject_name
=
answer
;
answer
=
NULL
;
/* Get the email addresses. */
tty_printf
(
_
(
"Enter email addresses"
));
tty_printf
(
_
(
" (end with an empty line):
\n
"
));
ask_mb_lines
(
&
mb_email
,
"Name-Email: "
);
/* DNS names. */
tty_printf
(
_
(
"Enter DNS names"
));
tty_printf
(
_
(
" (optional; end with an empty line):
\n
"
));
ask_mb_lines
(
&
mb_dns
,
"Name-DNS: "
);
/* URIs. */
tty_printf
(
_
(
"Enter URIs"
));
tty_printf
(
_
(
" (optional; end with an empty line):
\n
"
));
ask_mb_lines
(
&
mb_uri
,
"Name-URI: "
);
/* Want a self-signed certificate? */
selfsigned
=
tty_get_answer_is_yes
(
_
(
"Create self-signed certificate? (y/N) "
));
/* Put it all together. */
store_key_value_lf
(
&
mb_result
,
"Key-Type: "
,
keytype
);
{
char
numbuf
[
30
];
snprintf
(
numbuf
,
sizeof
numbuf
,
"%u"
,
nbits
);
store_key_value_lf
(
&
mb_result
,
"Key-Length: "
,
numbuf
);
}
if
(
keygrip
)
store_key_value_lf
(
&
mb_result
,
"Key-Grip: "
,
keygrip
);
store_key_value_lf
(
&
mb_result
,
"Key-Usage: "
,
keyusage
);
if
(
selfsigned
)
store_key_value_lf
(
&
mb_result
,
"Serial: "
,
"random"
);
store_key_value_lf
(
&
mb_result
,
"Name-DN: "
,
subject_name
);
if
(
store_mb_lines
(
&
mb_result
,
&
mb_email
))
goto
mem_error
;
if
(
store_mb_lines
(
&
mb_result
,
&
mb_dns
))
goto
mem_error
;
if
(
store_mb_lines
(
&
mb_result
,
&
mb_uri
))
goto
mem_error
;
put_membuf
(
&
mb_result
,
""
,
1
);
result
=
get_membuf
(
&
mb_result
,
NULL
);
if
(
!
result
)
goto
mem_error
;
tty_printf
(
_
(
"These parameters are used:
\n
"
));
for
(
s
=
result
;
(
s2
=
strchr
(
s
,
'\n'
));
s
=
s2
+
1
)
tty_printf
(
" %.*s
\n
"
,
(
int
)(
s2
-
s
),
s
);
tty_printf
(
"
\n
"
);
if
(
!
tty_get_answer_is_yes
(
"Proceed with creation? (y/N) "
))
goto
leave
;
/* Now create a parameter file and generate the key. */
fp
=
es_fopenmem
(
0
,
"w+"
);
if
(
!
fp
)
{
log_error
(
_
(
"error creating temporary file: %s
\n
"
),
strerror
(
errno
));
goto
leave
;
}
es_fputs
(
result
,
fp
);
es_rewind
(
fp
);
if
(
selfsigned
)
tty_printf
(
"%s"
,
_
(
"Now creating self-signed certificate. "
));
else
tty_printf
(
"%s"
,
_
(
"Now creating certificate request. "
));
tty_printf
(
"%s"
,
_
(
"This may take a while ...
\n
"
));
{
int
save_pem
=
ctrl
->
create_pem
;
ctrl
->
create_pem
=
1
;
/* Force creation of PEM. */
err
=
gpgsm_genkey
(
ctrl
,
fp
,
output_stream
);
ctrl
->
create_pem
=
save_pem
;
}
if
(
!
err
)
{
if
(
selfsigned
)
tty_printf
(
_
(
"Ready.
\n
"
));
else
tty_printf
(
_
(
"Ready. You should now send this request to your CA.
\n
"
));
}
goto
leave
;
mem_error
:
log_error
(
_
(
"resource problem: out of core
\n
"
));
leave
:
es_fclose
(
fp
);
xfree
(
answer
);
xfree
(
subject_name
);
xfree
(
keytype_buffer
);
xfree
(
keygrip
);
xfree
(
get_membuf
(
&
mb_email
,
NULL
));
xfree
(
get_membuf
(
&
mb_dns
,
NULL
));
xfree
(
get_membuf
(
&
mb_uri
,
NULL
));
xfree
(
get_membuf
(
&
mb_result
,
NULL
));
xfree
(
result
);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Tue, Apr 22, 3:53 AM (23 h, 2 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
69/a6/6fdb18d010ced54f8bed68bbadfd
Attached To
rG GnuPG
Event Timeline
Log In to Comment