diff options
author | Dave Brolley <brolley@redhat.com> | 2009-08-06 12:25:50 -0400 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2009-08-06 12:25:50 -0400 |
commit | 3c96130fde2f114d0ecca13870ac91b00219cf6c (patch) | |
tree | 4872acd81f6f1bcd1539946e598bfa4afc8accd9 /runtime/staprun/modverify.c | |
parent | dceb9cebada8326f7eb5097475303c28e81b105b (diff) | |
download | systemtap-steved-3c96130fde2f114d0ecca13870ac91b00219cf6c.tar.gz systemtap-steved-3c96130fde2f114d0ecca13870ac91b00219cf6c.tar.xz systemtap-steved-3c96130fde2f114d0ecca13870ac91b00219cf6c.zip |
2009-08-06 Dave Brolley <brolley@redhat.com>
* modverify.c (staprun.h): #include it.
(verify_it): Now accepts module data and signature data as arguments.
Don't open and read the signature here. Don't read the module here.
(verify_module): Now accepts module data as argument. Read the signature
once here.
* modverify.h (verify_module): Now accepts module data as argument.
* staprun.c (main): Don't call check_permissions here.
* staprun.h (check_permissions): Prototype removed.
* staprun_funcs.c (check_permissions): Now static. Accepts module data
as argument. Pass module data to check_signature.
(insert_module): Canonicalize the module path early here. Call
check_permissions here, passing it the mapped module data.
(check_signature): Now accepts module data as argument. Pass the module
data to verify_module.
(check_path): Use the already-canonicalized module path.
Diffstat (limited to 'runtime/staprun/modverify.c')
-rw-r--r-- | runtime/staprun/modverify.c | 168 |
1 files changed, 73 insertions, 95 deletions
diff --git a/runtime/staprun/modverify.c b/runtime/staprun/modverify.c index f4b15ac3..15447279 100644 --- a/runtime/staprun/modverify.c +++ b/runtime/staprun/modverify.c @@ -29,6 +29,7 @@ #include <certt.h> #include "nsscommon.h" +#include "staprun.h" #include "modverify.h" #include <sys/stat.h> @@ -130,7 +131,11 @@ check_cert_db_permissions (const char *cert_db_path) { return 0; } - rc = 1; /* ok */ + if (! S_ISDIR (info.st_mode)) + { + fprintf (stderr, "Certificate database %s is not a directory.\n", cert_db_path); + return 0; + } /* The owner of the database must be root. */ if (info.st_uid != 0) @@ -139,6 +144,8 @@ check_cert_db_permissions (const char *cert_db_path) { rc = 0; } + rc = 1; /* ok */ + /* Check the database directory access permissions */ if ((info.st_mode & S_IRUSR) == 0) fprintf (stderr, "Certificate database %s should be readable by the owner.\n", cert_db_path); @@ -189,16 +196,75 @@ check_cert_db_permissions (const char *cert_db_path) { } static int -verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pubKey) +verify_it (const char *signatureName, const SECItem *signature, + const void *module_data, off_t module_size, + const SECKEYPublicKey *pubKey) { - unsigned char buffer[4096]; - PRFileInfo info; + VFYContext *vfy; + SECStatus secStatus; + + /* Create a verification context. */ + vfy = VFY_CreateContextDirect (pubKey, signature, SEC_OID_PKCS1_RSA_ENCRYPTION, + SEC_OID_UNKNOWN, NULL, NULL); + if (! vfy) + { + /* The key does not match the signature. This is not an error. It just + means we are currently trying the wrong certificate/key. i.e. the + module remains untrusted for now. */ + return MODULE_UNTRUSTED; + } + + /* Begin the verification process. */ + secStatus = VFY_Begin(vfy); + if (secStatus != SECSuccess) + { + fprintf (stderr, "Unable to initialize verification context while verifying %s using the signature in %s.\n", + modpath, signatureName); + nssError (); + return MODULE_CHECK_ERROR; + } + + /* Add the data to be verified. */ + secStatus = VFY_Update (vfy, module_data, module_size); + if (secStatus != SECSuccess) + { + fprintf (stderr, "Error while verifying %s using the signature in %s.\n", + modpath, signatureName); + nssError (); + return MODULE_CHECK_ERROR; + } + + /* Complete the verification. */ + secStatus = VFY_End (vfy); + if (secStatus != SECSuccess) { + fprintf (stderr, "Unable to verify the signed module %s. It may have been altered since it was created.\n", + modpath); + nssError (); + return MODULE_ALTERED; + } + + return MODULE_OK; +} + +int verify_module (const char *signatureName, const void *module_data, + off_t module_size) +{ + const char *dbdir = SYSCONFDIR "/systemtap/staprun"; + SECKEYPublicKey *pubKey; + SECStatus secStatus; + CERTCertList *certList; + CERTCertListNode *certListNode; + CERTCertificate *cert; PRStatus prStatus; + PRFileInfo info; PRInt32 numBytes; PRFileDesc *local_file_fd; - VFYContext *vfy; SECItem signature; - SECStatus secStatus; + int rc = 0; + + /* Verify the permissions of the certificate database and its files. */ + if (! check_cert_db_permissions (dbdir)) + return MODULE_UNTRUSTED; /* Get the size of the signature file. */ prStatus = PR_GetFileInfo (signatureName, &info); @@ -246,94 +312,6 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu /* Done with the signature file. */ PR_Close (local_file_fd); - /* Create a verification context. */ - vfy = VFY_CreateContextDirect (pubKey, & signature, SEC_OID_PKCS1_RSA_ENCRYPTION, - SEC_OID_UNKNOWN, NULL, NULL); - if (! vfy) - { - /* The key does not match the signature. This is not an error. It just means - we are currently trying the wrong certificate/key. i.e. the module - remains untrusted for now. */ - return MODULE_UNTRUSTED; - } - - /* Begin the verification process. */ - secStatus = VFY_Begin(vfy); - if (secStatus != SECSuccess) - { - fprintf (stderr, "Unable to initialize verification context while verifying %s using the signature in %s.\n", - inputName, signatureName); - nssError (); - return MODULE_CHECK_ERROR; - } - - /* Now read the data and add it to the signature. */ - local_file_fd = PR_Open (inputName, PR_RDONLY, 0); - if (local_file_fd == NULL) - { - fprintf (stderr, "Could not open module file %s.\n", inputName); - nssError (); - return MODULE_CHECK_ERROR; - } - - for (;;) - { - numBytes = PR_Read (local_file_fd, buffer, sizeof (buffer)); - if (numBytes == 0) - break; /* EOF */ - - if (numBytes < 0) - { - fprintf (stderr, "Error reading module file %s.\n", inputName); - nssError (); - return MODULE_CHECK_ERROR; - } - - /* Add the data to the signature. */ - secStatus = VFY_Update (vfy, buffer, numBytes); - if (secStatus != SECSuccess) - { - fprintf (stderr, "Error while verifying module file %s.\n", inputName); - nssError (); - return MODULE_CHECK_ERROR; - } - } - - PR_Close(local_file_fd); - - /* Complete the verification. */ - secStatus = VFY_End (vfy); - if (secStatus != SECSuccess) { - fprintf (stderr, "Unable to verify signed module %s. It may have been altered since it was created.\n", inputName); - nssError (); - return MODULE_ALTERED; - } - - return MODULE_OK; -} - -int verify_module (const char *module_name, const char *signature_name) -{ - const char *dbdir = SYSCONFDIR "/systemtap/staprun"; - SECKEYPublicKey *pubKey; - SECStatus secStatus; - CERTCertList *certList; - CERTCertListNode *certListNode; - CERTCertificate *cert; - PRStatus prStatus; - PRFileInfo info; - int rc = 0; - - /* Look for the certificate database. If it's not there, it's not an error, it - just means that the module can't be verified. */ - prStatus = PR_GetFileInfo (dbdir, &info); - if (prStatus != PR_SUCCESS || info.type != PR_FILE_DIRECTORY) - return MODULE_UNTRUSTED; - - /* Verify the permissions of the certificate database and its files. */ - if (! check_cert_db_permissions (dbdir)) - return MODULE_UNTRUSTED; - /* Call the NSPR initialization routines. */ PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); @@ -373,7 +351,7 @@ int verify_module (const char *module_name, const char *signature_name) } /* Verify the file. */ - rc = verify_it (module_name, signature_name, pubKey); + rc = verify_it (signatureName, & signature, module_data, module_size, pubKey); if (rc == MODULE_OK || rc == MODULE_ALTERED || rc == MODULE_CHECK_ERROR) break; /* resolved or error */ } |