Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Kea
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
426
Issues
426
List
Boards
Labels
Service Desk
Milestones
Merge Requests
67
Merge Requests
67
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
ISC Open Source Projects
Kea
Commits
3fe98e57
Commit
3fe98e57
authored
Aug 05, 2014
by
Tomek Mrugalski
🛰
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[3417] Obsolete directory src/bin/cmdctl removed.
parent
fe5928ed
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
0 additions
and
669 deletions
+0
-669
src/bin/cmdctl/openssl-certgen.cc
src/bin/cmdctl/openssl-certgen.cc
+0
-416
src/bin/cmdctl/tests/openssl-certgen_test.py
src/bin/cmdctl/tests/openssl-certgen_test.py
+0
-253
No files found.
src/bin/cmdctl/openssl-certgen.cc
deleted
100644 → 0
View file @
fe5928ed
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <cstring>
#include <iostream>
#include <fstream>
#include <memory>
#include <getopt.h>
// For cleaner 'does not exist or is not readable' output than
// openssl provides
#include <unistd.h>
#include <errno.h>
// This is a simple tool that creates a self-signed PEM certificate
// for use with BIND 10. It creates a simple certificate for initial
// setup. Currently, all values are hardcoded defaults. For future
// versions, we may want to add more options for administrators.
// It will create a PEM file containing a certificate with the following
// values:
// common name: localhost
// organization: BIND10
// country code: US
// Additional error return codes; these are specifically
// chosen to be distinct from validation error codes as
// provided by OpenSSL. Their main use is to distinguish
// error cases in the unit tests.
const
int
DECODING_ERROR
=
100
;
const
int
BAD_OPTIONS
=
101
;
const
int
READ_ERROR
=
102
;
const
int
WRITE_ERROR
=
103
;
const
int
UNKNOWN_ERROR
=
104
;
const
int
NO_SUCH_FILE
=
105
;
const
int
FILE_PERMISSION_ERROR
=
106
;
void
usage
()
{
std
::
cout
<<
"Usage: b10-certgen [OPTION]..."
<<
std
::
endl
;
std
::
cout
<<
"Validate, create, or update a self-signed certificate for "
"use with b10-cmdctl"
<<
std
::
endl
;
std
::
cout
<<
""
<<
std
::
endl
;
std
::
cout
<<
"Options:"
<<
std
::
endl
;
std
::
cout
<<
"-c, --certfile=FILE
\t\t
file to read or store the certificate"
<<
std
::
endl
;
std
::
cout
<<
"-f, --force
\t\t\t
overwrite existing certificate even if it"
<<
std
::
endl
<<
"
\t\t\t\t
is valid"
<<
std
::
endl
;
std
::
cout
<<
"-h, --help
\t\t\t
show this help"
<<
std
::
endl
;
std
::
cout
<<
"-k, --keyfile=FILE
\t\t
file to store the generated private key"
<<
std
::
endl
;
std
::
cout
<<
"-w, --write
\t\t\t
create a new certificate if the given file"
<<
std
::
endl
<<
"
\t\t\t\t
does not exist, or if is is not valid"
<<
std
::
endl
;
std
::
cout
<<
"-q, --quiet
\t\t\t
print no output when creating or validating"
<<
std
::
endl
;
}
/// \brief Returns true if the given file exists
///
/// \param filename The file to check
/// \return true if file exists
bool
fileExists
(
const
std
::
string
&
filename
)
{
return
(
access
(
filename
.
c_str
(),
F_OK
)
==
0
);
}
/// \brief Returns true if the given file exists and is readable
///
/// \param filename The file to check
/// \return true if file exists and is readable
bool
fileIsReadable
(
const
std
::
string
&
filename
)
{
return
(
access
(
filename
.
c_str
(),
R_OK
)
==
0
);
}
/// \brief Returns true if the given file exists and is writable
///
/// \param filename The file to check
/// \return true if file exists and is writable
bool
fileIsWritable
(
const
std
::
string
&
filename
)
{
return
(
access
(
filename
.
c_str
(),
W_OK
)
==
0
);
}
class
CertificateTool
{
public:
CertificateTool
(
bool
quiet
)
:
quiet_
(
quiet
)
{}
int
createKeyAndCertificate
(
const
std
::
string
&
key_file_name
,
const
std
::
string
&
cert_file_name
)
{
// Create and store a private key
print
(
"Creating key file "
+
key_file_name
);
RSA
*
rsa
=
RSA_generate_key
(
2048
,
65537UL
,
NULL
,
NULL
);
std
::
ofstream
key_file
(
key_file_name
.
c_str
());
if
(
!
key_file
.
good
())
{
print
(
std
::
string
(
"Error writing to "
)
+
key_file_name
+
": "
+
std
::
strerror
(
errno
));
return
(
WRITE_ERROR
);
}
BIO
*
key_mem
=
BIO_new
(
BIO_s_mem
());
PEM_write_bio_RSAPrivateKey
(
key_mem
,
rsa
,
NULL
,
NULL
,
0
,
NULL
,
NULL
);
char
*
p
;
long
len
=
BIO_get_mem_data
(
key_mem
,
&
p
);
key_file
.
write
(
p
,
(
unsigned
)
len
);
BIO_free
(
key_mem
);
if
(
!
key_file
.
good
())
{
print
(
std
::
string
(
"Error writing to "
)
+
key_file_name
+
": "
+
std
::
strerror
(
errno
));
return
(
WRITE_ERROR
);
}
key_file
.
close
();
// Certificate options, currently hardcoded.
// For a future version we may want to make these
// settable.
X509
*
cert
=
X509_new
();
X509_set_version
(
cert
,
2
);
BIGNUM
*
serial
=
BN_new
();
BN_pseudo_rand
(
serial
,
64
,
0
,
0
);
BN_to_ASN1_INTEGER
(
serial
,
X509_get_serialNumber
(
cert
));
BN_free
(
serial
);
X509_NAME
*
name
=
X509_get_subject_name
(
cert
);
std
::
string
cn
(
"localhost"
);
X509_NAME_add_entry_by_NID
(
name
,
NID_commonName
,
MBSTRING_ASC
,
(
unsigned
char
*
)
cn
.
c_str
(),
cn
.
size
(),
-
1
,
0
);
std
::
string
org
(
"UNKNOWN"
);
X509_NAME_add_entry_by_NID
(
name
,
NID_organizationName
,
MBSTRING_ASC
,
(
unsigned
char
*
)
org
.
c_str
(),
org
.
size
(),
-
1
,
0
);
std
::
string
cc
(
"XX"
);
X509_NAME_add_entry_by_NID
(
name
,
NID_countryName
,
MBSTRING_ASC
,
(
unsigned
char
*
)
cc
.
c_str
(),
cc
.
size
(),
-
1
,
0
);
X509_set_issuer_name
(
cert
,
name
);
X509_gmtime_adj
(
X509_get_notBefore
(
cert
),
0
);
X509_gmtime_adj
(
X509_get_notAfter
(
cert
),
60
*
60
*
24
*
365L
);
EVP_PKEY
*
pkey
=
EVP_PKEY_new
();
EVP_PKEY_assign_RSA
(
pkey
,
rsa
);
X509_set_pubkey
(
cert
,
pkey
);
X509V3_CTX
ec
;
X509V3_set_ctx_nodb
(
&
ec
);
X509V3_set_ctx
(
&
ec
,
cert
,
cert
,
NULL
,
NULL
,
0
);
const
std
::
string
bc_val
(
"critical,CA:TRUE,pathlen:1"
);
X509_EXTENSION
*
bc
=
X509V3_EXT_conf_nid
(
NULL
,
&
ec
,
NID_basic_constraints
,
(
char
*
)
bc_val
.
c_str
());
X509_add_ext
(
cert
,
bc
,
-
1
);
X509_EXTENSION_free
(
bc
);
const
std
::
string
ku_val
=
(
"critical,keyCertSign,cRLSign"
);
X509_EXTENSION
*
ku
=
X509V3_EXT_conf_nid
(
NULL
,
&
ec
,
NID_key_usage
,
(
char
*
)
ku_val
.
c_str
());
X509_add_ext
(
cert
,
ku
,
-
1
);
X509_EXTENSION_free
(
ku
);
const
std
::
string
ski_val
(
"hash"
);
X509_EXTENSION
*
ski
=
X509V3_EXT_conf_nid
(
NULL
,
&
ec
,
NID_subject_key_identifier
,
(
char
*
)
ski_val
.
c_str
());
X509_add_ext
(
cert
,
ski
,
-
1
);
X509_EXTENSION_free
(
ski
);
X509_sign
(
cert
,
pkey
,
EVP_sha256
());
print
(
"Creating certificate file "
+
cert_file_name
);
std
::
ofstream
cert_file
(
cert_file_name
.
c_str
());
if
(
!
cert_file
.
good
())
{
print
(
std
::
string
(
"Error writing to "
)
+
cert_file_name
+
": "
+
std
::
strerror
(
errno
));
return
(
WRITE_ERROR
);
}
BIO
*
cert_mem
=
BIO_new
(
BIO_s_mem
());
PEM_write_bio_X509
(
cert_mem
,
cert
);
p
=
NULL
;
len
=
BIO_get_mem_data
(
cert_mem
,
&
p
);
cert_file
.
write
(
p
,
(
unsigned
)
len
);
BIO_free
(
cert_mem
);
if
(
!
cert_file
.
good
())
{
print
(
std
::
string
(
"Error writing to "
)
+
cert_file_name
+
": "
+
std
::
strerror
(
errno
));
return
(
WRITE_ERROR
);
}
cert_file
.
close
();
X509_free
(
cert
);
RSA_free
(
rsa
);
return
(
0
);
}
int
validateCertificate
(
const
std
::
string
&
certfile
)
{
// Since we are dealing with a self-signed certificate here, we
// also use the certificate to check itself; i.e. we add it
// as a trusted certificate, then validate the certificate itself.
BIO
*
in
=
BIO_new_file
(
certfile
.
c_str
(),
"r"
);
if
(
in
==
NULL
)
{
print
(
"failed to read "
+
certfile
);
return
(
READ_ERROR
);
}
X509
*
cert
=
PEM_read_bio_X509
(
in
,
NULL
,
NULL
,
NULL
);
BIO_free
(
in
);
if
(
cert
==
NULL
)
{
print
(
"failed to decode "
+
certfile
);
return
(
DECODING_ERROR
);
}
X509_STORE
*
store
=
X509_STORE_new
();
X509_STORE_CTX
*
csc
=
X509_STORE_CTX_new
();
X509_STORE_CTX_init
(
csc
,
store
,
cert
,
NULL
);
STACK_OF
(
X509
)
*
trusted
=
sk_X509_new_null
();
sk_X509_push
(
trusted
,
X509_dup
(
cert
));
X509_STORE_CTX_trusted_stack
(
csc
,
trusted
);
const
int
result
=
X509_verify_cert
(
csc
);
const
int
cerror
=
X509_STORE_CTX_get_error
(
csc
);
X509_STORE_CTX_free
(
csc
);
X509_free
(
cert
);
if
(
result
>
0
)
{
print
(
certfile
+
" is valid"
);
return
(
X509_V_OK
);
}
else
{
print
(
certfile
+
" failed to verify: "
+
X509_verify_cert_error_string
(
cerror
));
return
(
cerror
);
}
}
/// \brief Runs the tool
///
/// \param create_cert Create certificate if true, validate if false.
/// Does nothing if certificate exists and is valid.
/// \param force_create Create new certificate even if it is valid.
/// \param certfile Certificate file to read to or write from.
/// \param keyfile Key file to write if certificate is created.
/// Ignored if create_cert is false
/// \return zero on success, non-zero on failure
int
run
(
bool
create_cert
,
bool
force_create
,
const
std
::
string
&
certfile
,
const
std
::
string
&
keyfile
)
{
if
(
create_cert
)
{
// Unless force is given, only create it if the current
// one is not OK
// First do some basic permission checks; both files
// should either not exist, or be both readable
// and writable
// The checks are done one by one so all errors can
// be enumerated in one go
if
(
fileExists
(
certfile
))
{
if
(
!
fileIsReadable
(
certfile
))
{
print
(
certfile
+
" not readable: "
+
std
::
strerror
(
errno
));
create_cert
=
false
;
}
if
(
!
fileIsWritable
(
certfile
))
{
print
(
certfile
+
" not writable: "
+
std
::
strerror
(
errno
));
create_cert
=
false
;
}
}
// The key file really only needs write permissions (for
// b10-certgen that is)
if
(
fileExists
(
keyfile
))
{
if
(
!
fileIsWritable
(
keyfile
))
{
print
(
keyfile
+
" not writable: "
+
std
::
strerror
(
errno
));
create_cert
=
false
;
}
}
if
(
!
create_cert
)
{
print
(
"Not creating new certificate, "
"check file permissions"
);
return
(
FILE_PERMISSION_ERROR
);
}
// If we reach this, we know that if they exist, we can both
// read and write them, so now it's up to content checking
// and/or force_create
if
(
force_create
||
!
fileExists
(
certfile
)
||
validateCertificate
(
certfile
)
!=
X509_V_OK
)
{
return
(
createKeyAndCertificate
(
keyfile
,
certfile
));
}
else
{
print
(
"Not creating a new certificate (use -f to force)"
);
}
}
else
{
if
(
!
fileExists
(
certfile
))
{
print
(
certfile
+
": "
+
std
::
strerror
(
errno
));
return
(
NO_SUCH_FILE
);
}
if
(
!
fileIsReadable
(
certfile
))
{
print
(
certfile
+
" not readable: "
+
std
::
strerror
(
errno
));
return
(
FILE_PERMISSION_ERROR
);
}
int
result
=
validateCertificate
(
certfile
);
if
(
result
!=
0
)
{
print
(
"Running with -w would overwrite the certificate"
);
}
return
(
result
);
}
return
(
0
);
}
private:
/// Prints the message to stdout unless quiet_ is true
void
print
(
const
std
::
string
&
msg
)
{
if
(
!
quiet_
)
{
std
::
cout
<<
msg
<<
std
::
endl
;
}
}
bool
quiet_
;
};
int
main
(
int
argc
,
char
*
argv
[])
{
// ERR_load_crypto_strings();
// create or check certificate
bool
create_cert
=
false
;
// force creation even if not necessary
bool
force_create
=
false
;
// don't print any output
bool
quiet
=
false
;
// default certificate file
std
::
string
certfile
(
"cmdctl-certfile.pem"
);
// default key file
std
::
string
keyfile
(
"cmdctl-keyfile.pem"
);
// whether or not the above values have been
// overridden (used in command line checking)
bool
certfile_default
=
true
;
bool
keyfile_default
=
true
;
// It would appear some environments insist on
// char* here (Sunstudio on Solaris), so we const_cast
// them to get rid of compiler warnings.
const
struct
option
long_options
[]
=
{
{
const_cast
<
char
*>
(
"certfile"
),
required_argument
,
NULL
,
'c'
},
{
const_cast
<
char
*>
(
"force"
),
no_argument
,
NULL
,
'f'
},
{
const_cast
<
char
*>
(
"help"
),
no_argument
,
NULL
,
'h'
},
{
const_cast
<
char
*>
(
"keyfile"
),
required_argument
,
NULL
,
'k'
},
{
const_cast
<
char
*>
(
"write"
),
no_argument
,
NULL
,
'w'
},
{
const_cast
<
char
*>
(
"quiet"
),
no_argument
,
NULL
,
'q'
},
{
NULL
,
0
,
NULL
,
0
}
};
int
opt
,
option_index
;
while
((
opt
=
getopt_long
(
argc
,
argv
,
"c:fhk:wq"
,
long_options
,
&
option_index
))
!=
-
1
)
{
switch
(
opt
)
{
case
'c'
:
certfile
=
optarg
;
certfile_default
=
false
;
break
;
case
'f'
:
force_create
=
true
;
break
;
case
'h'
:
usage
();
return
(
0
);
break
;
case
'k'
:
keyfile
=
optarg
;
keyfile_default
=
false
;
break
;
case
'w'
:
create_cert
=
true
;
break
;
case
'q'
:
quiet
=
true
;
break
;
default:
// A message will have already been output about the error.
return
(
BAD_OPTIONS
);
}
}
if
(
optind
<
argc
)
{
std
::
cout
<<
"Error: extraneous arguments"
<<
std
::
endl
<<
std
::
endl
;
usage
();
return
(
BAD_OPTIONS
);
}
// Some sanity checks on option combinations
if
(
create_cert
&&
(
certfile_default
^
keyfile_default
))
{
std
::
cout
<<
"Error: keyfile and certfile must both be specified "
"if one of them is when calling b10-certgen in write "
"mode."
<<
std
::
endl
;
return
(
BAD_OPTIONS
);
}
if
(
!
create_cert
&&
!
keyfile_default
)
{
std
::
cout
<<
"Error: keyfile is not used when not in write mode"
<<
std
::
endl
;
return
(
BAD_OPTIONS
);
}
// Initialize the tool and perform the appropriate action(s)
CertificateTool
tool
(
quiet
);
return
(
tool
.
run
(
create_cert
,
force_create
,
certfile
,
keyfile
));
}
src/bin/cmdctl/tests/openssl-certgen_test.py
deleted
100644 → 0
View file @
fe5928ed
# Copyright (C) 2014 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# Note: the main code is in C++, but what we are mostly testing is
# options and behaviour (output/file creation, etc), which is easier
# to test in python.
import
unittest
import
os
from
subprocess
import
call
import
subprocess
import
ssl
import
stat
def
run
(
command
):
"""
Small helper function that returns a tuple of (rcode, stdout, stderr) after
running the given command (an array of command and arguments, as passed on
to subprocess).
"""
subp
=
subprocess
.
Popen
(
command
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
(
stdout
,
stderr
)
=
subp
.
communicate
()
return
(
subp
.
returncode
,
stdout
,
stderr
)
class
FileDeleterContext
:
"""
Simple Context Manager that deletes a given set of files when the context
is left.
"""
def
__init__
(
self
,
files
):
self
.
files
=
files
def
__enter__
(
self
):
pass
def
__exit__
(
self
,
type
,
value
,
traceback
):
for
f
in
self
.
files
:
if
os
.
path
.
exists
(
f
):
os
.
unlink
(
f
)
class
FilePermissionContext
:
"""
Simple Context Manager that temporarily modifies file permissions for
a given file
"""
def
__init__
(
self
,
f
,
unset_flags
=
[],
set_flags
=
[]):
"""
Initialize file permission context.
See the stat module for possible flags to set or unset.
The flags are changed when the context is entered (i.e.
you can create the context first without any change)
The flags are changed back when the context is left.
Parameters:
f: string, file to change permissions for
unset_flags: list of flags to unset
set_flags: list of flags to set
"""
self
.
file
=
f
self
.
orig_mode
=
os
.
stat
(
f
).
st_mode
new_mode
=
self
.
orig_mode
for
flag
in
unset_flags
:
new_mode
=
new_mode
&
~
flag
for
flag
in
set_flags
:
new_mode
=
new_mode
|
flag
self
.
new_mode
=
new_mode
def
__enter__
(
self
):
os
.
chmod
(
self
.
file
,
self
.
new_mode
)
def
__exit__
(
self
,
type
,
value
,
traceback
):
os
.
chmod
(
self
.
file
,
self
.
orig_mode
)
def
read_file_data
(
filename
):
"""
Simple text file reader that returns its contents as an array
"""
with
open
(
filename
)
as
f
:
return
f
.
readlines
()
class
TestCertGenTool
(
unittest
.
TestCase
):
TOOL
=
'../b10-certgen'
def
run_check
(
self
,
expected_returncode
,
expected_stdout
,
expected_stderr
,
command
):
"""
Runs the given command, and checks return code, and outputs (if provided).
Arguments:
expected_returncode, return code of the command
expected_stdout, (multiline) string that is checked agains stdout.
May be None, in which case the check is skipped.
expected_stderr, (multiline) string that is checked agains stderr.
May be None, in which case the check is skipped.
"""
(
returncode
,
stdout
,
stderr
)
=
run
(
command
)
self
.
assertEqual
(
expected_returncode
,
returncode
,
" "
.
join
(
command
))
if
expected_stdout
is
not
None
:
self
.
assertEqual
(
expected_stdout
,
stdout
.
decode
())
if
expected_stderr
is
not
None
:
self
.
assertEqual
(
expected_stderr
,
stderr
.
decode
())
def
validate_certificate
(
self
,
expected_result
,
certfile
):
"""
Validate a certificate, using the quiet option of the tool; it runs
the check option (-c) for the given base name of the certificate (-f
<certfile>), and compares the return code to the given
expected_result value
"""
self
.
run_check
(
expected_result
,
''
,
''
,
[
self
.
TOOL
,
'-q'
,
'-c'
,
certfile
])
# Same with long options
self
.
run_check
(
expected_result
,
''
,
''
,
[
self
.
TOOL
,
'--quiet'
,
'--certfile'
,
certfile
])
def
test_basic_creation
(
self
):
"""
Tests whether basic creation with no arguments (except output
file name) successfully creates a key and certificate
"""
keyfile
=
'test-keyfile.pem'
certfile
=
'test-certfile.pem'
command
=
[
self
.
TOOL
,
'-q'
,
'-w'
,
'-c'
,
certfile
,
'-k'
,
keyfile
]
self
.
creation_helper
(
command
,
certfile
,
keyfile
)
# Do same with long options
command
=
[
self
.
TOOL
,
'--quiet'
,
'--write'
,
'--certfile='
+
certfile
,
'--keyfile='
+
keyfile
]
self
.
creation_helper
(
command
,
certfile
,
keyfile
)
def
creation_helper
(
self
,
command
,
certfile
,
keyfile
):
"""
Helper method for test_basic_creation.
Performs the actual checks
"""
with
FileDeleterContext
([
keyfile
,
certfile
]):
self
.
assertFalse
(
os
.
path
.
exists
(
keyfile
))
self
.
assertFalse
(
os
.
path
.
exists
(
certfile
))
self
.
run_check
(
0
,
''
,
''
,
command
)
self
.
assertTrue
(
os
.
path
.
exists
(
keyfile
))
self
.
assertTrue
(
os
.
path
.
exists
(
certfile
))
# Validate the certificate that was just created
self
.
validate_certificate
(
0
,
certfile
)
# When run with the same options, it should *not* create it again,
# as the current certificate should still be valid
certdata
=
read_file_data
(
certfile
)
keydata
=
read_file_data
(
keyfile
)
self
.
run_check
(
0
,
''
,
''
,
command
)
self
.
assertEqual
(
certdata
,
read_file_data
(
certfile
))
self
.
assertEqual
(
keydata
,
read_file_data
(
keyfile
))
# but if we add -f, it should force a new creation
command
.
append
(
'-f'
)
self
.
run_check
(
0
,
''
,
''
,
command
)
self
.
assertNotEqual
(
certdata
,
read_file_data
(
certfile
))
self
.
assertNotEqual
(
keydata
,
read_file_data
(
keyfile
))
def
test_check_bad_certificates
(
self
):
"""
Tests a few pre-created certificates with the -c option
"""
path
=
os
.
environ
[
'CMDCTL_SRC_PATH'
]
+
'/tests/testdata/'
self
.
validate_certificate
(
10
,
path
+
'expired-certfile.pem'
)
self
.
validate_certificate
(
100
,
path
+
'mangled-certfile.pem'
)
self
.
validate_certificate
(
20
,
path
+
'noca-certfile.pem'
)
def
test_bad_options
(
self
):
"""
Tests some combinations of commands that should fail.
"""
# specify -c but not -k
self
.
run_check
(
101
,
'Error: keyfile and certfile must both be specified '
'if one of them is when calling b10-certgen in write '
'mode.
\n
'
,
''
,
[
self
.
TOOL
,
'-w'
,
'-c'
,
'foo'
])
self
.
run_check
(
101
,
'Error: keyfile and certfile must both be specified '
'if one of them is when calling b10-certgen in write '
'mode.
\n
'
,
''
,
[
self
.
TOOL
,
'-w'
,
'-k'
,
'foo'
])
self
.
run_check
(
101
,
'Error: keyfile is not used when not in write mode
\n
'
,
''
,
[
self
.
TOOL
,
'-k'
,
'foo'
])
# Extraneous argument
self
.
run_check
(
101
,
None
,
None
,
[
self
.
TOOL
,
'foo'
])
# No such file
self
.
run_check
(
105
,
None
,
None
,
[
self
.
TOOL
,
'-c'
,
'foo'
])
@
unittest
.
skipIf
(
os
.
getuid
()
==
0
,
'test cannot be run as root user'
)
def
test_permissions
(
self
):
"""
Test some combinations of correct and bad permissions.
"""
keyfile
=
'mod-keyfile.pem'
certfile
=
'mod-certfile.pem'
command
=
[
self
.
TOOL
,
'-q'
,
'-w'
,
'-c'
,
certfile
,
'-k'
,
keyfile
]
# Delete them at the end