Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * logging.c
- *
- * provide logging functions for Microservices
- */
- #include "../include/logging.h"
- static char skeyfile[MAXFILENAMELEN] = "/tmp/skey";
- static char pkeyfile[MAXFILENAMELEN] = "/tmp/pkey";
- static const int querysize = 3 * 1024 + 200 ; // hopefully this is enough.. this allows max size (256) for each field and 200 extra bytes for the query itself
- int
- setfname ( char *target, const char *fname )
- {
- return ( snprintf ( target, MAXFILENAMELEN, "%s", fname ) );
- }
- void
- print_pgresult ( PGresult **res )
- {
- // printf("res %d\n",res);
- int nFields;
- int i;
- int j;
- /* first, print out the attribute names */
- nFields = PQnfields ( *res );
- for ( i = 0; i < nFields; i++ )
- printf ( "%-15s", PQfname ( *res, i ) );
- printf ( "\n\n" );
- /* next, print out the rows */
- for ( i = 0; i < PQntuples ( *res ); i++ )
- {
- for ( j = 0; j < nFields; j++ )
- printf ( "%-15s", PQgetvalue ( *res, i, j ) );
- printf ( "\n" );
- }
- // /* clear res to avoid memleaks*/
- // PQclear ( res );
- }
- PGresult*
- pquery ( const char *query )
- {
- PGresult *res;
- /*
- * so far the postgresql server does not support ssl later the sslmode=require option should be added
- * the password and username for the database as well as the host can and should be provided by kerberos
- * (no way to reproduce this because of missing infrastructure
- *
- * creating a new connection for every query is not pretty but works for now
- */
- const char *conninfo;
- conninfo = "host = faracvs.cs.uni-magdeburg.de user=shaman dbname = shamanlog password=blasentee";
- conn = PQconnectdb ( conninfo );
- /* Check to see that the backend connection was successfully made */
- if ( PQstatus ( conn ) != CONNECTION_OK )
- {
- fprintf ( stderr, "Connection to database failed: %s", PQerrorMessage ( conn ) );
- PQfinish ( conn );
- // TODO - create and return an invalid result
- return ( NULL );
- }
- /* Query DB*/
- res = PQexec ( conn, query );
- /* close the connection to the database and cleanup */
- PQfinish ( conn );
- return ( res );
- }
- void
- make_sign_parameters ( gcry_sexp_t *sign_parms, const char *plain )
- {
- size_t errof = 0;
- int rc;
- size_t nscanned;
- size_t hash_len = gcry_md_get_algo_dlen ( HASH_TYPE );
- unsigned char *digest;
- gcry_mpi_t mpival;
- gcry_error_t error;
- digest = malloc ( hash_len );
- gcry_md_hash_buffer ( HASH_TYPE, digest, plain, strlen ( plain ) );
- int i;
- for (i=0;i<hash_len;i++)
- printf("%02x ",digest[i]);
- printf("\n");
- error = gcry_mpi_scan ( &mpival, GCRYMPI_FMT_USG, digest, hash_len, &nscanned );
- assert ( error == 0 );
- printf ( "nscanned: %lu\n", nscanned );
- rc = gcry_sexp_build ( sign_parms, &errof,
- "(data (flags pkcs1) (hash %s %m))",
- HASH_NAME, mpival );
- assert ( rc == 0 );
- gcry_mpi_release ( mpival );
- free ( digest );
- }
- gcry_error_t
- verifysig ( char* message, gcry_sexp_t sig, gcry_sexp_t pubkey )
- {
- gcry_sexp_t sign_parms;
- gcry_error_t rc;
- // Verification
- make_sign_parameters ( &sign_parms, message );
- rc = gcry_pk_verify ( sig, sign_parms, pubkey );
- return rc;
- }
- int
- write_sexptofile ( const char *filename, gcry_sexp_t *sexp )
- {
- int len;
- char *buffer;
- FILE *handle;
- int retval;
- // len = sexptochar ( &buffer, sexp );
- len = gcry_sexp_sprint ( *sexp, GCRYSEXP_FMT_ADVANCED, NULL , 0 );
- buffer = malloc ( len );
- len = gcry_sexp_sprint ( *sexp, GCRYSEXP_FMT_ADVANCED, buffer , len );
- handle = fopen ( filename, "w" );
- retval = fwrite ( buffer, len, 1, handle );
- fclose ( handle );
- free ( buffer );
- return ( retval );
- }
- int
- read_sexpfromfile ( const char *filename , gcry_sexp_t *sexp )
- {
- size_t errof = 0;
- int retval;
- char buffer[BUFFER_MAXSIZE];
- gcry_error_t rc;
- int i;
- FILE *handle;
- for ( i = 0;i < BUFFER_MAXSIZE;i++ )
- {
- buffer[i] = '\0';
- }
- handle = fopen ( filename, "r" );
- if ( handle == 0 )
- {
- perror ( "file could not be opened" );
- }
- retval = fread ( buffer, BUFFER_MAXSIZE, 1, handle );
- rc = gcry_sexp_build ( sexp, &errof, buffer );
- assert ( rc == 0 );
- return ( retval );
- }
- // TODO - FIX SO THAT WE CAN OBTAIN A KEY FOR A SPECIFIC MICROSERVICE BASED ON A LIST SOMEWHERE WHICH IS CERTIFIED AND SIGNED BY SOME ROOT KEY WHICH EVERYONE HAS
- void
- obtainkeys ( gcry_sexp_t* skey, gcry_sexp_t* pubkey )
- {
- size_t errof = 0;
- gcry_sexp_t keypair, gen_parms;
- gcry_error_t rc;
- FILE *handle, *handle2;
- handle = fopen ( pkeyfile, "r" );
- handle2 = fopen ( skeyfile, "r" );
- // no secmem needed for gcrypt
- gcry_control ( GCRYCTL_DISABLE_SECMEM, 0 );
- if ( ( handle == 0 ) || ( handle2 == 0 ) )
- {
- printf ( "no keys found - generating\n" );
- // create key
- rc = gcry_sexp_build ( &gen_parms, &errof, "(genkey (rsa (nbits 3:512)))" );
- assert ( rc == 0 );
- rc = gcry_pk_genkey ( &keypair, gen_parms );
- assert ( rc == 0 );
- *skey = gcry_sexp_find_token ( keypair, "private-key", 0 );
- *pubkey = gcry_sexp_find_token ( keypair, "public-key", 0 );
- assert ( skey != NULL );
- assert ( pubkey != NULL );
- // close files if they were opened
- if ( handle != 0 )
- fclose ( handle );
- if ( handle2 != 0 )
- fclose ( handle2 );
- printf ( "closed files\n" );
- // write key to file
- write_sexptofile ( pkeyfile, pubkey );
- write_sexptofile ( skeyfile, skey );
- }
- else
- {
- // both files opened, so close them again - before reading keys
- if ( handle != 0 )
- fclose ( handle );
- if ( handle2 != 0 )
- fclose ( handle2 );
- read_sexpfromfile ( pkeyfile , pubkey );
- read_sexpfromfile ( skeyfile , skey );
- assert ( skey != NULL );
- assert ( pubkey != NULL );
- }
- }
- void
- print_sexp ( gcry_sexp_t sexp )
- {
- int len;
- char *buffer;
- len = gcry_sexp_sprint ( sexp, GCRYSEXP_FMT_ADVANCED, NULL , 0 );
- buffer = malloc ( len );
- len = gcry_sexp_sprint ( sexp, GCRYSEXP_FMT_ADVANCED, buffer , len );
- printf ( "sexp: %s\n", buffer );
- free ( buffer );
- }
- gcry_error_t sign ( const char *message, gcry_sexp_t *sig, gcry_sexp_t *skey )
- {
- // generate signature
- gcry_sexp_t sign_parms;
- gcry_error_t rc;
- make_sign_parameters ( &sign_parms, message );
- print_sexp ( sign_parms );
- rc = gcry_pk_sign ( sig, sign_parms, *skey );
- return rc;
- }
- int logmessage ( const char *user, const char *service, const char *dig_obj, const char * message )
- {
- struct timeval tp;
- char timestmp[100]; // play it safe - currently we only need ~ 20 bytes
- char query[querysize];
- char smessage[querysize];
- char *signature;
- int len; //length of the signature
- gcry_sexp_t skey, pkey;
- gcry_sexp_t sig;
- gcry_error_t rc;
- PGresult *res;
- if ( gettimeofday ( &tp, NULL ) != 0 )
- {
- perror ( "could not get time - exiting logmessage unsuccessfully\n" );
- return ( -1 );
- }
- snprintf ( timestmp, 100, "%ld,%ld", ( unsigned long ) tp.tv_sec, ( unsigned long ) tp.tv_usec );
- snprintf ( smessage, querysize, "%s%s%s%s%s", timestmp, message, service, user, dig_obj );
- obtainkeys ( &skey, &pkey ); // TODO this needs to be rewritten to obtain a key for a specific Micro Service - depending on what we get for service here - maybe within the database?
- rc = sign ( smessage, &sig, &skey );
- if ( rc != 0 )
- {
- printf ( "sign returns error %d: %s\n - exiting logmessage unsuccessfully\n", rc, gcry_strerror ( rc ) );
- exit ( -1 );
- }
- len = gcry_sexp_sprint ( sig, GCRYSEXP_FMT_ADVANCED, NULL , 0 );
- signature = malloc ( len );
- if ( signature == NULL )
- {
- perror ( "malloc failed - exiting logmessage unsuccessfully\n" );
- return ( -1 );
- }
- len = gcry_sexp_sprint ( sig, GCRYSEXP_FMT_ADVANCED, signature , len );
- snprintf ( query, querysize, "insert into logpile(time, logstring, service, username, dig_obj, signature) values('%s','%s','%s','%s','%s','%s')", timestmp, message, service, user, dig_obj, signature );
- free ( signature );
- res = pquery ( query );
- if ( PQresultStatus ( res ) != PGRES_COMMAND_OK )
- {
- printf ( "There was an error while executing the following query: %s\nexiting logmessage()\n", query );
- // TODO - SQL Fehler mit hinschreiben
- return ( -1 );
- }
- PQclear ( res );
- return ( 0 );
- }
- long long mypow ( long long i, long long j )
- {
- if ( j == 0 )
- return ( 1 );
- return ( ( i*mypow ( i, j - 1 ) ) );
- }
- long long stringtolong ( const char *id )
- {
- long long iid = 0;
- int i;
- printf ( "id: %s\n", id );
- for ( i = strlen ( id );i > 0;i-- )
- {
- iid = iid + ( ( ( int ) id[strlen ( id )-i] ) - 48 ) * mypow ( 10, i - 1 );
- }
- printf ( "iid: %lld\n", iid );
- return ( iid );
- }
- long long verifyrows ( char *dig_obj, unsigned long long id )
- {
- // verifies log entries for digital object dig_obj starting at ID=id
- PGresult *res;
- char query[querysize];
- snprintf ( query, 2048, "select * from logpile where dig_obj ='%s' and ID >= '%llx'", dig_obj , id );
- res = pquery ( query );
- if ( PQresultStatus ( res ) != PGRES_TUPLES_OK )
- {
- printf ( "There was an error while executing the following query: %s\n exiting verifyrows()\n", query );
- // TODO - SQL Fehler mit hinschreiben
- return ( -1 );
- }
- int nFields;
- int i;
- int j;
- /* first, print out the attribute names */
- nFields = PQnfields ( res );
- // for ( i = 0; i < nFields; i++ )
- // printf ( "%-15s", PQfname ( *res, i ) );
- // printf ( "\n\n" );
- char smessage[querysize];
- gcry_sexp_t skey, pkey, sig;
- obtainkeys ( &skey, &pkey );
- /* next, print out the rows */
- for ( i = 0; i < PQntuples ( res ); i++ )
- {
- // initialize smessage for next row
- char id[100];
- unsigned long long iid;
- char signature[querysize];
- smessage[0] = '\0';
- size_t errof = 0;
- gcry_error_t rc;
- for ( j = 0; j < nFields; j++ )
- {
- if ( ( j != 0 ) && ( j != ( nFields - 1 ) ) )
- {
- // j=0 and j=(nFields-1) means that the current field is the id or signature which are not part of the signed string
- // TODO - double check if PQgetvalue really is \0 terminated
- snprintf ( &smessage[strlen ( smessage ) ], querysize - strlen ( smessage ) - strlen ( PQgetvalue ( res, i, j ) ), "%s", PQgetvalue ( res, i, j ) );
- }
- if ( j == 0 )
- snprintf ( id, 100, "%s", PQgetvalue ( res, i, j ) );
- else if ( j == ( nFields - 1 ) )
- snprintf ( signature, querysize, "%s", PQgetvalue ( res, i, j ) );
- }
- // process current row
- // create signature from obtained sig-string from db
- rc = gcry_sexp_build ( &sig, &errof, signature );
- if ( rc != 0 )
- {
- printf ( "signature for ID='%s' from database is invalid\nexiting verifyrows()\n", id );
- iid = stringtolong ( id );
- return ( iid );
- }
- printf ( "smessage: '%s'\n", smessage );
- printf ( "signatur: '%s'\n", signature );
- rc = verifysig ( smessage, sig, pkey );
- if ( rc != 0 )
- {
- printf ( "%i,verify returns exit code %d: %s\nexiting verifyrows()\n", gcry_err_code ( rc ), rc, gcry_strerror ( rc ) );
- // errorcode for system failure
- iid = -1;
- printf ( "There seems to be an issue with the error code of verifysig\n causing it to return 'conflicting use' instead of BAD SIGNATURE\nso things might fall apart from here on\n" );
- // error code for wrong signature = ID
- if ( gcry_err_code ( rc ) == GPG_ERR_BAD_SIGNATURE )
- iid = stringtolong ( id );
- return ( iid );
- };
- }
- /* clear res to avoid memleaks*/
- PQclear ( res );
- return ( 0 );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement