Advertisement
Guest User

erika

a guest
Jan 19th, 2009
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.85 KB | None | 0 0
  1. /*
  2. * logging.c
  3. *
  4. * provide logging functions for Microservices
  5. */
  6. #include "../include/logging.h"
  7.  
  8. static char skeyfile[MAXFILENAMELEN] = "/tmp/skey";
  9. static char pkeyfile[MAXFILENAMELEN] = "/tmp/pkey";
  10. 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
  11.  
  12. int
  13. setfname ( char *target, const char *fname )
  14. {
  15. return ( snprintf ( target, MAXFILENAMELEN, "%s", fname ) );
  16. }
  17.  
  18. void
  19. print_pgresult ( PGresult **res )
  20. {
  21. // printf("res %d\n",res);
  22. int nFields;
  23. int i;
  24. int j;
  25.  
  26. /* first, print out the attribute names */
  27. nFields = PQnfields ( *res );
  28.  
  29. for ( i = 0; i < nFields; i++ )
  30. printf ( "%-15s", PQfname ( *res, i ) );
  31.  
  32. printf ( "\n\n" );
  33.  
  34. /* next, print out the rows */
  35. for ( i = 0; i < PQntuples ( *res ); i++ )
  36. {
  37. for ( j = 0; j < nFields; j++ )
  38. printf ( "%-15s", PQgetvalue ( *res, i, j ) );
  39.  
  40. printf ( "\n" );
  41. }
  42.  
  43. // /* clear res to avoid memleaks*/
  44. // PQclear ( res );
  45. }
  46.  
  47. PGresult*
  48. pquery ( const char *query )
  49. {
  50. PGresult *res;
  51.  
  52. /*
  53. * so far the postgresql server does not support ssl later the sslmode=require option should be added
  54. * the password and username for the database as well as the host can and should be provided by kerberos
  55. * (no way to reproduce this because of missing infrastructure
  56. *
  57. * creating a new connection for every query is not pretty but works for now
  58. */
  59.  
  60. const char *conninfo;
  61. conninfo = "host = faracvs.cs.uni-magdeburg.de user=shaman dbname = shamanlog password=blasentee";
  62.  
  63. conn = PQconnectdb ( conninfo );
  64.  
  65. /* Check to see that the backend connection was successfully made */
  66.  
  67. if ( PQstatus ( conn ) != CONNECTION_OK )
  68. {
  69. fprintf ( stderr, "Connection to database failed: %s", PQerrorMessage ( conn ) );
  70. PQfinish ( conn );
  71. // TODO - create and return an invalid result
  72. return ( NULL );
  73. }
  74.  
  75. /* Query DB*/
  76. res = PQexec ( conn, query );
  77.  
  78. /* close the connection to the database and cleanup */
  79. PQfinish ( conn );
  80.  
  81. return ( res );
  82. }
  83.  
  84. void
  85. make_sign_parameters ( gcry_sexp_t *sign_parms, const char *plain )
  86. {
  87. size_t errof = 0;
  88. int rc;
  89. size_t nscanned;
  90. size_t hash_len = gcry_md_get_algo_dlen ( HASH_TYPE );
  91. unsigned char *digest;
  92. gcry_mpi_t mpival;
  93. gcry_error_t error;
  94.  
  95. digest = malloc ( hash_len );
  96. gcry_md_hash_buffer ( HASH_TYPE, digest, plain, strlen ( plain ) );
  97. int i;
  98. for (i=0;i<hash_len;i++)
  99. printf("%02x ",digest[i]);
  100. printf("\n");
  101.  
  102. error = gcry_mpi_scan ( &mpival, GCRYMPI_FMT_USG, digest, hash_len, &nscanned );
  103. assert ( error == 0 );
  104. printf ( "nscanned: %lu\n", nscanned );
  105. rc = gcry_sexp_build ( sign_parms, &errof,
  106. "(data (flags pkcs1) (hash %s %m))",
  107. HASH_NAME, mpival );
  108. assert ( rc == 0 );
  109. gcry_mpi_release ( mpival );
  110. free ( digest );
  111. }
  112.  
  113. gcry_error_t
  114. verifysig ( char* message, gcry_sexp_t sig, gcry_sexp_t pubkey )
  115. {
  116. gcry_sexp_t sign_parms;
  117. gcry_error_t rc;
  118.  
  119. // Verification
  120. make_sign_parameters ( &sign_parms, message );
  121. rc = gcry_pk_verify ( sig, sign_parms, pubkey );
  122.  
  123. return rc;
  124. }
  125.  
  126. int
  127. write_sexptofile ( const char *filename, gcry_sexp_t *sexp )
  128. {
  129. int len;
  130. char *buffer;
  131. FILE *handle;
  132. int retval;
  133.  
  134. // len = sexptochar ( &buffer, sexp );
  135. len = gcry_sexp_sprint ( *sexp, GCRYSEXP_FMT_ADVANCED, NULL , 0 );
  136. buffer = malloc ( len );
  137. len = gcry_sexp_sprint ( *sexp, GCRYSEXP_FMT_ADVANCED, buffer , len );
  138.  
  139.  
  140. handle = fopen ( filename, "w" );
  141. retval = fwrite ( buffer, len, 1, handle );
  142. fclose ( handle );
  143. free ( buffer );
  144. return ( retval );
  145. }
  146.  
  147.  
  148. int
  149. read_sexpfromfile ( const char *filename , gcry_sexp_t *sexp )
  150. {
  151. size_t errof = 0;
  152.  
  153. int retval;
  154. char buffer[BUFFER_MAXSIZE];
  155. gcry_error_t rc;
  156. int i;
  157. FILE *handle;
  158.  
  159. for ( i = 0;i < BUFFER_MAXSIZE;i++ )
  160. {
  161. buffer[i] = '\0';
  162. }
  163.  
  164. handle = fopen ( filename, "r" );
  165.  
  166. if ( handle == 0 )
  167. {
  168. perror ( "file could not be opened" );
  169. }
  170.  
  171. retval = fread ( buffer, BUFFER_MAXSIZE, 1, handle );
  172.  
  173. rc = gcry_sexp_build ( sexp, &errof, buffer );
  174. assert ( rc == 0 );
  175.  
  176.  
  177. return ( retval );
  178. }
  179.  
  180. // 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
  181. void
  182. obtainkeys ( gcry_sexp_t* skey, gcry_sexp_t* pubkey )
  183. {
  184. size_t errof = 0;
  185. gcry_sexp_t keypair, gen_parms;
  186. gcry_error_t rc;
  187. FILE *handle, *handle2;
  188. handle = fopen ( pkeyfile, "r" );
  189. handle2 = fopen ( skeyfile, "r" );
  190.  
  191. // no secmem needed for gcrypt
  192. gcry_control ( GCRYCTL_DISABLE_SECMEM, 0 );
  193.  
  194. if ( ( handle == 0 ) || ( handle2 == 0 ) )
  195. {
  196. printf ( "no keys found - generating\n" );
  197. // create key
  198. rc = gcry_sexp_build ( &gen_parms, &errof, "(genkey (rsa (nbits 3:512)))" );
  199. assert ( rc == 0 );
  200. rc = gcry_pk_genkey ( &keypair, gen_parms );
  201. assert ( rc == 0 );
  202.  
  203. *skey = gcry_sexp_find_token ( keypair, "private-key", 0 );
  204. *pubkey = gcry_sexp_find_token ( keypair, "public-key", 0 );
  205. assert ( skey != NULL );
  206. assert ( pubkey != NULL );
  207. // close files if they were opened
  208.  
  209. if ( handle != 0 )
  210. fclose ( handle );
  211.  
  212. if ( handle2 != 0 )
  213. fclose ( handle2 );
  214.  
  215. printf ( "closed files\n" );
  216.  
  217. // write key to file
  218. write_sexptofile ( pkeyfile, pubkey );
  219.  
  220. write_sexptofile ( skeyfile, skey );
  221. }
  222.  
  223. else
  224. {
  225. // both files opened, so close them again - before reading keys
  226. if ( handle != 0 )
  227. fclose ( handle );
  228.  
  229. if ( handle2 != 0 )
  230. fclose ( handle2 );
  231.  
  232. read_sexpfromfile ( pkeyfile , pubkey );
  233.  
  234. read_sexpfromfile ( skeyfile , skey );
  235.  
  236. assert ( skey != NULL );
  237.  
  238. assert ( pubkey != NULL );
  239. }
  240. }
  241.  
  242. void
  243. print_sexp ( gcry_sexp_t sexp )
  244. {
  245. int len;
  246. char *buffer;
  247.  
  248. len = gcry_sexp_sprint ( sexp, GCRYSEXP_FMT_ADVANCED, NULL , 0 );
  249. buffer = malloc ( len );
  250. len = gcry_sexp_sprint ( sexp, GCRYSEXP_FMT_ADVANCED, buffer , len );
  251. printf ( "sexp: %s\n", buffer );
  252. free ( buffer );
  253. }
  254.  
  255. gcry_error_t sign ( const char *message, gcry_sexp_t *sig, gcry_sexp_t *skey )
  256. {
  257. // generate signature
  258. gcry_sexp_t sign_parms;
  259. gcry_error_t rc;
  260.  
  261. make_sign_parameters ( &sign_parms, message );
  262. print_sexp ( sign_parms );
  263. rc = gcry_pk_sign ( sig, sign_parms, *skey );
  264.  
  265. return rc;
  266. }
  267.  
  268. int logmessage ( const char *user, const char *service, const char *dig_obj, const char * message )
  269. {
  270.  
  271. struct timeval tp;
  272. char timestmp[100]; // play it safe - currently we only need ~ 20 bytes
  273.  
  274.  
  275. char query[querysize];
  276. char smessage[querysize];
  277. char *signature;
  278. int len; //length of the signature
  279.  
  280. gcry_sexp_t skey, pkey;
  281. gcry_sexp_t sig;
  282. gcry_error_t rc;
  283.  
  284. PGresult *res;
  285.  
  286. if ( gettimeofday ( &tp, NULL ) != 0 )
  287. {
  288. perror ( "could not get time - exiting logmessage unsuccessfully\n" );
  289. return ( -1 );
  290. }
  291.  
  292. snprintf ( timestmp, 100, "%ld,%ld", ( unsigned long ) tp.tv_sec, ( unsigned long ) tp.tv_usec );
  293.  
  294. snprintf ( smessage, querysize, "%s%s%s%s%s", timestmp, message, service, user, dig_obj );
  295.  
  296. 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?
  297.  
  298. rc = sign ( smessage, &sig, &skey );
  299.  
  300. if ( rc != 0 )
  301. {
  302. printf ( "sign returns error %d: %s\n - exiting logmessage unsuccessfully\n", rc, gcry_strerror ( rc ) );
  303. exit ( -1 );
  304. }
  305.  
  306. len = gcry_sexp_sprint ( sig, GCRYSEXP_FMT_ADVANCED, NULL , 0 );
  307.  
  308. signature = malloc ( len );
  309.  
  310. if ( signature == NULL )
  311. {
  312. perror ( "malloc failed - exiting logmessage unsuccessfully\n" );
  313. return ( -1 );
  314. }
  315.  
  316. len = gcry_sexp_sprint ( sig, GCRYSEXP_FMT_ADVANCED, signature , len );
  317.  
  318. 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 );
  319.  
  320. free ( signature );
  321.  
  322. res = pquery ( query );
  323.  
  324. if ( PQresultStatus ( res ) != PGRES_COMMAND_OK )
  325. {
  326. printf ( "There was an error while executing the following query: %s\nexiting logmessage()\n", query );
  327. // TODO - SQL Fehler mit hinschreiben
  328. return ( -1 );
  329. }
  330.  
  331. PQclear ( res );
  332.  
  333. return ( 0 );
  334. }
  335.  
  336. long long mypow ( long long i, long long j )
  337. {
  338. if ( j == 0 )
  339. return ( 1 );
  340.  
  341. return ( ( i*mypow ( i, j - 1 ) ) );
  342. }
  343.  
  344. long long stringtolong ( const char *id )
  345. {
  346. long long iid = 0;
  347. int i;
  348. printf ( "id: %s\n", id );
  349.  
  350. for ( i = strlen ( id );i > 0;i-- )
  351. {
  352. iid = iid + ( ( ( int ) id[strlen ( id )-i] ) - 48 ) * mypow ( 10, i - 1 );
  353. }
  354.  
  355. printf ( "iid: %lld\n", iid );
  356.  
  357. return ( iid );
  358. }
  359.  
  360. long long verifyrows ( char *dig_obj, unsigned long long id )
  361. {
  362. // verifies log entries for digital object dig_obj starting at ID=id
  363. PGresult *res;
  364. char query[querysize];
  365.  
  366. snprintf ( query, 2048, "select * from logpile where dig_obj ='%s' and ID >= '%llx'", dig_obj , id );
  367.  
  368. res = pquery ( query );
  369.  
  370. if ( PQresultStatus ( res ) != PGRES_TUPLES_OK )
  371. {
  372. printf ( "There was an error while executing the following query: %s\n exiting verifyrows()\n", query );
  373. // TODO - SQL Fehler mit hinschreiben
  374. return ( -1 );
  375. }
  376.  
  377. int nFields;
  378.  
  379. int i;
  380. int j;
  381.  
  382. /* first, print out the attribute names */
  383. nFields = PQnfields ( res );
  384. // for ( i = 0; i < nFields; i++ )
  385. // printf ( "%-15s", PQfname ( *res, i ) );
  386. // printf ( "\n\n" );
  387. char smessage[querysize];
  388.  
  389. gcry_sexp_t skey, pkey, sig;
  390. obtainkeys ( &skey, &pkey );
  391.  
  392. /* next, print out the rows */
  393.  
  394. for ( i = 0; i < PQntuples ( res ); i++ )
  395. {
  396. // initialize smessage for next row
  397. char id[100];
  398. unsigned long long iid;
  399. char signature[querysize];
  400. smessage[0] = '\0';
  401. size_t errof = 0;
  402. gcry_error_t rc;
  403.  
  404. for ( j = 0; j < nFields; j++ )
  405. {
  406. if ( ( j != 0 ) && ( j != ( nFields - 1 ) ) )
  407. {
  408. // j=0 and j=(nFields-1) means that the current field is the id or signature which are not part of the signed string
  409.  
  410. // TODO - double check if PQgetvalue really is \0 terminated
  411. snprintf ( &smessage[strlen ( smessage ) ], querysize - strlen ( smessage ) - strlen ( PQgetvalue ( res, i, j ) ), "%s", PQgetvalue ( res, i, j ) );
  412. }
  413.  
  414. if ( j == 0 )
  415. snprintf ( id, 100, "%s", PQgetvalue ( res, i, j ) );
  416. else if ( j == ( nFields - 1 ) )
  417. snprintf ( signature, querysize, "%s", PQgetvalue ( res, i, j ) );
  418. }
  419.  
  420. // process current row
  421. // create signature from obtained sig-string from db
  422. rc = gcry_sexp_build ( &sig, &errof, signature );
  423.  
  424. if ( rc != 0 )
  425. {
  426. printf ( "signature for ID='%s' from database is invalid\nexiting verifyrows()\n", id );
  427. iid = stringtolong ( id );
  428. return ( iid );
  429. }
  430.  
  431. printf ( "smessage: '%s'\n", smessage );
  432.  
  433. printf ( "signatur: '%s'\n", signature );
  434.  
  435. rc = verifysig ( smessage, sig, pkey );
  436.  
  437. if ( rc != 0 )
  438. {
  439. printf ( "%i,verify returns exit code %d: %s\nexiting verifyrows()\n", gcry_err_code ( rc ), rc, gcry_strerror ( rc ) );
  440. // errorcode for system failure
  441. iid = -1;
  442. 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" );
  443. // error code for wrong signature = ID
  444.  
  445. if ( gcry_err_code ( rc ) == GPG_ERR_BAD_SIGNATURE )
  446. iid = stringtolong ( id );
  447.  
  448. return ( iid );
  449. };
  450. }
  451.  
  452. /* clear res to avoid memleaks*/
  453. PQclear ( res );
  454.  
  455. return ( 0 );
  456. }
  457.  
  458.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement