diff options
Diffstat (limited to 'src/credential/plugin_rest_credential.c')
-rw-r--r-- | src/credential/plugin_rest_credential.c | 258 |
1 files changed, 243 insertions, 15 deletions
diff --git a/src/credential/plugin_rest_credential.c b/src/credential/plugin_rest_credential.c index 11e6fb276..2df65d7ad 100644 --- a/src/credential/plugin_rest_credential.c +++ b/src/credential/plugin_rest_credential.c | |||
@@ -37,6 +37,14 @@ | |||
37 | 37 | ||
38 | #define GNUNET_REST_API_NS_CREDENTIAL "/credential" | 38 | #define GNUNET_REST_API_NS_CREDENTIAL "/credential" |
39 | 39 | ||
40 | #define GNUNET_REST_API_NS_CREDENTIAL_ISSUE "/credential/issue" | ||
41 | |||
42 | #define GNUNET_REST_API_NS_CREDENTIAL_VERIFY "/credential/verify" | ||
43 | |||
44 | #define GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION "expiration" | ||
45 | |||
46 | #define GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY "subject_key" | ||
47 | |||
40 | #define GNUNET_REST_JSONAPI_CREDENTIAL "credential" | 48 | #define GNUNET_REST_JSONAPI_CREDENTIAL "credential" |
41 | 49 | ||
42 | #define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential" | 50 | #define GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO "credential" |
@@ -57,7 +65,7 @@ struct Plugin | |||
57 | 65 | ||
58 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 66 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
59 | 67 | ||
60 | struct VerifyHandle | 68 | struct RequestHandle |
61 | { | 69 | { |
62 | /** | 70 | /** |
63 | * Handle to Credential service. | 71 | * Handle to Credential service. |
@@ -70,6 +78,21 @@ struct VerifyHandle | |||
70 | struct GNUNET_CREDENTIAL_Request *verify_request; | 78 | struct GNUNET_CREDENTIAL_Request *verify_request; |
71 | 79 | ||
72 | /** | 80 | /** |
81 | * Handle to issue request | ||
82 | */ | ||
83 | struct GNUNET_CREDENTIAL_Request *issue_request; | ||
84 | |||
85 | /** | ||
86 | * Handle to identity | ||
87 | */ | ||
88 | struct GNUNET_IDENTITY_Handle *identity; | ||
89 | |||
90 | /** | ||
91 | * Handle to identity operation | ||
92 | */ | ||
93 | struct GNUNET_IDENTITY_Operation *id_op; | ||
94 | |||
95 | /** | ||
73 | * Handle to rest request | 96 | * Handle to rest request |
74 | */ | 97 | */ |
75 | struct GNUNET_REST_RequestHandle *rest_handle; | 98 | struct GNUNET_REST_RequestHandle *rest_handle; |
@@ -133,7 +156,7 @@ struct VerifyHandle | |||
133 | * @param handle Handle to clean up | 156 | * @param handle Handle to clean up |
134 | */ | 157 | */ |
135 | static void | 158 | static void |
136 | cleanup_handle (struct VerifyHandle *handle) | 159 | cleanup_handle (struct RequestHandle *handle) |
137 | { | 160 | { |
138 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 161 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
139 | "Cleaning up\n"); | 162 | "Cleaning up\n"); |
@@ -145,16 +168,13 @@ cleanup_handle (struct VerifyHandle *handle) | |||
145 | if (NULL != handle->subject_attr) | 168 | if (NULL != handle->subject_attr) |
146 | GNUNET_free (handle->subject_attr); | 169 | GNUNET_free (handle->subject_attr); |
147 | if (NULL != handle->verify_request) | 170 | if (NULL != handle->verify_request) |
148 | { | ||
149 | GNUNET_CREDENTIAL_verify_cancel (handle->verify_request); | 171 | GNUNET_CREDENTIAL_verify_cancel (handle->verify_request); |
150 | handle->verify_request = NULL; | ||
151 | } | ||
152 | if (NULL != handle->credential) | 172 | if (NULL != handle->credential) |
153 | { | ||
154 | GNUNET_CREDENTIAL_disconnect (handle->credential); | 173 | GNUNET_CREDENTIAL_disconnect (handle->credential); |
155 | handle->credential = NULL; | 174 | if (NULL != handle->id_op) |
156 | } | 175 | GNUNET_IDENTITY_cancel (handle->id_op); |
157 | 176 | if (NULL != handle->identity) | |
177 | GNUNET_IDENTITY_disconnect (handle->identity); | ||
158 | if (NULL != handle->timeout_task) | 178 | if (NULL != handle->timeout_task) |
159 | { | 179 | { |
160 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | 180 | GNUNET_SCHEDULER_cancel (handle->timeout_task); |
@@ -172,7 +192,7 @@ cleanup_handle (struct VerifyHandle *handle) | |||
172 | static void | 192 | static void |
173 | do_error (void *cls) | 193 | do_error (void *cls) |
174 | { | 194 | { |
175 | struct VerifyHandle *handle = cls; | 195 | struct RequestHandle *handle = cls; |
176 | struct MHD_Response *resp; | 196 | struct MHD_Response *resp; |
177 | 197 | ||
178 | resp = GNUNET_REST_create_response (NULL); | 198 | resp = GNUNET_REST_create_response (NULL); |
@@ -280,7 +300,7 @@ handle_verify_response (void *cls, | |||
280 | struct GNUNET_CREDENTIAL_Credential *cred) | 300 | struct GNUNET_CREDENTIAL_Credential *cred) |
281 | { | 301 | { |
282 | 302 | ||
283 | struct VerifyHandle *handle = cls; | 303 | struct RequestHandle *handle = cls; |
284 | struct MHD_Response *resp; | 304 | struct MHD_Response *resp; |
285 | struct GNUNET_JSONAPI_Document *json_document; | 305 | struct GNUNET_JSONAPI_Document *json_document; |
286 | struct GNUNET_JSONAPI_Resource *json_resource; | 306 | struct GNUNET_JSONAPI_Resource *json_resource; |
@@ -355,7 +375,7 @@ verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, | |||
355 | const char* url, | 375 | const char* url, |
356 | void *cls) | 376 | void *cls) |
357 | { | 377 | { |
358 | struct VerifyHandle *handle = cls; | 378 | struct RequestHandle *handle = cls; |
359 | struct GNUNET_HashCode key; | 379 | struct GNUNET_HashCode key; |
360 | char *tmp; | 380 | char *tmp; |
361 | char *entity_attr; | 381 | char *entity_attr; |
@@ -478,6 +498,213 @@ verify_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, | |||
478 | 498 | ||
479 | } | 499 | } |
480 | 500 | ||
501 | void | ||
502 | send_cred_response (struct RequestHandle *handle, | ||
503 | struct GNUNET_CREDENTIAL_Credential *cred) | ||
504 | { | ||
505 | struct MHD_Response *resp; | ||
506 | struct GNUNET_JSONAPI_Document *json_document; | ||
507 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
508 | json_t *cred_obj; | ||
509 | char *result; | ||
510 | char *issuer; | ||
511 | char *subject; | ||
512 | char *signature; | ||
513 | char *id; | ||
514 | |||
515 | GNUNET_assert (NULL == cred); | ||
516 | issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key); | ||
517 | if (NULL == issuer) | ||
518 | { | ||
519 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
520 | "Subject malformed\n"); | ||
521 | return; | ||
522 | } | ||
523 | GNUNET_asprintf (&id, | ||
524 | "%s.%s", | ||
525 | issuer, | ||
526 | (char*)&cred[1]); | ||
527 | subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key); | ||
528 | if (NULL == subject) | ||
529 | { | ||
530 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
531 | "Subject malformed\n"); | ||
532 | return; | ||
533 | } | ||
534 | GNUNET_STRINGS_base64_encode ((char*)&cred->signature, | ||
535 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature), | ||
536 | &signature); | ||
537 | json_document = GNUNET_JSONAPI_document_new (); | ||
538 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_CREDENTIAL_TYPEINFO, | ||
539 | id); | ||
540 | GNUNET_free (id); | ||
541 | cred_obj = json_object(); | ||
542 | json_object_set_new (cred_obj, "issuer", json_string (issuer)); | ||
543 | json_object_set_new (cred_obj, "subject", json_string (subject)); | ||
544 | json_object_set_new (cred_obj, "expiration", json_integer( cred->expiration.abs_value_us)); | ||
545 | json_object_set_new (cred_obj, "signature", json_string (signature)); | ||
546 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
547 | GNUNET_REST_JSONAPI_CREDENTIAL, | ||
548 | cred_obj); | ||
549 | GNUNET_JSONAPI_document_resource_add (json_document, json_resource); | ||
550 | GNUNET_JSONAPI_document_serialize (json_document, &result); | ||
551 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
552 | "Result %s\n", | ||
553 | result); | ||
554 | json_decref (cred_obj); | ||
555 | GNUNET_JSONAPI_document_delete (json_document); | ||
556 | resp = GNUNET_REST_create_response (result); | ||
557 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
558 | GNUNET_free (result); | ||
559 | GNUNET_free (signature); | ||
560 | GNUNET_free (issuer); | ||
561 | GNUNET_free (subject); | ||
562 | cleanup_handle (handle); | ||
563 | } | ||
564 | |||
565 | void | ||
566 | get_cred_issuer_cb (void *cls, | ||
567 | struct GNUNET_IDENTITY_Ego *ego, | ||
568 | void **ctx, | ||
569 | const char *name) | ||
570 | { | ||
571 | struct RequestHandle *handle = cls; | ||
572 | struct GNUNET_TIME_Absolute etime_abs; | ||
573 | struct GNUNET_TIME_Relative etime_rel; | ||
574 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer_key; | ||
575 | struct GNUNET_HashCode key; | ||
576 | struct GNUNET_CREDENTIAL_Credential *cred; | ||
577 | char* expiration_str; | ||
578 | char* tmp; | ||
579 | |||
580 | handle->id_op = NULL; | ||
581 | |||
582 | if (NULL == name) | ||
583 | { | ||
584 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
585 | "Issuer not configured!\n"); | ||
586 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
587 | return; | ||
588 | } | ||
589 | |||
590 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
591 | "Connecting to credential service...\n"); | ||
592 | handle->credential = GNUNET_CREDENTIAL_connect (cfg); | ||
593 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
594 | "Connected\n"); | ||
595 | if (NULL == handle->credential) | ||
596 | { | ||
597 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
598 | "Connecting to CREDENTIAL failed\n"); | ||
599 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
600 | return; | ||
601 | } | ||
602 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION, | ||
603 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_EXPIRATION), | ||
604 | &key); | ||
605 | if ( GNUNET_NO == | ||
606 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
607 | &key) ) | ||
608 | { | ||
609 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
610 | "Missing expiration\n"); | ||
611 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
612 | return; | ||
613 | } | ||
614 | expiration_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | ||
615 | &key); | ||
616 | if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expiration_str, | ||
617 | &etime_rel)) | ||
618 | { | ||
619 | etime_abs = GNUNET_TIME_relative_to_absolute (etime_rel); | ||
620 | } else if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (expiration_str, | ||
621 | &etime_abs)) | ||
622 | { | ||
623 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
624 | "Malformed expiration: %s\n", expiration_str); | ||
625 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
626 | return; | ||
627 | } | ||
628 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR, | ||
629 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_ISSUER_ATTR), | ||
630 | &key); | ||
631 | if ( GNUNET_NO == | ||
632 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
633 | &key) ) | ||
634 | { | ||
635 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
636 | "Missing issuer attribute\n"); | ||
637 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
638 | return; | ||
639 | } | ||
640 | handle->issuer_attr = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get | ||
641 | (handle->rest_handle->url_param_map, | ||
642 | &key)); | ||
643 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY, | ||
644 | strlen (GNUNET_REST_JSONAPI_CREDENTIAL_SUBJECT_KEY), | ||
645 | &key); | ||
646 | if ( GNUNET_NO == | ||
647 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
648 | &key) ) | ||
649 | { | ||
650 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
651 | "Missing subject\n"); | ||
652 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
653 | return; | ||
654 | } | ||
655 | tmp = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | ||
656 | &key); | ||
657 | if (NULL == tmp) | ||
658 | { | ||
659 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
660 | "Malformed subject\n"); | ||
661 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
662 | return; | ||
663 | } | ||
664 | if (GNUNET_OK != | ||
665 | GNUNET_CRYPTO_ecdsa_public_key_from_string (tmp, | ||
666 | strlen (tmp), | ||
667 | &handle->subject_key)) { | ||
668 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
669 | "Malformed subject key\n"); | ||
670 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
671 | return; | ||
672 | } | ||
673 | issuer_key = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
674 | cred = GNUNET_CREDENTIAL_credential_issue (issuer_key, | ||
675 | &handle->subject_key, | ||
676 | handle->issuer_attr, | ||
677 | &etime_abs); | ||
678 | if (NULL == cred) | ||
679 | { | ||
680 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
681 | "Failed to create credential\n"); | ||
682 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
683 | return; | ||
684 | } | ||
685 | send_cred_response (handle, cred); | ||
686 | } | ||
687 | |||
688 | |||
689 | static void | ||
690 | issue_cred_cont (struct GNUNET_REST_RequestHandle *conndata_handle, | ||
691 | const char* url, | ||
692 | void *cls) | ||
693 | { | ||
694 | struct RequestHandle *handle = cls; | ||
695 | |||
696 | handle->identity = GNUNET_IDENTITY_connect (cfg, | ||
697 | NULL, | ||
698 | NULL); | ||
699 | handle->id_op = GNUNET_IDENTITY_get(handle->identity, | ||
700 | "credential-issuer", | ||
701 | &get_cred_issuer_cb, | ||
702 | handle); | ||
703 | handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
704 | &do_error, | ||
705 | handle); | ||
706 | } | ||
707 | |||
481 | /** | 708 | /** |
482 | * Handle rest request | 709 | * Handle rest request |
483 | * | 710 | * |
@@ -489,7 +716,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
489 | void *cls) | 716 | void *cls) |
490 | { | 717 | { |
491 | struct MHD_Response *resp; | 718 | struct MHD_Response *resp; |
492 | struct VerifyHandle *handle = cls; | 719 | struct RequestHandle *handle = cls; |
493 | 720 | ||
494 | //For GNS, independent of path return all options | 721 | //For GNS, independent of path return all options |
495 | resp = GNUNET_REST_create_response (NULL); | 722 | resp = GNUNET_REST_create_response (NULL); |
@@ -519,7 +746,7 @@ rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handl | |||
519 | GNUNET_REST_ResultProcessor proc, | 746 | GNUNET_REST_ResultProcessor proc, |
520 | void *proc_cls) | 747 | void *proc_cls) |
521 | { | 748 | { |
522 | struct VerifyHandle *handle = GNUNET_new (struct VerifyHandle); | 749 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); |
523 | struct GNUNET_REST_RequestHandlerError err; | 750 | struct GNUNET_REST_RequestHandlerError err; |
524 | 751 | ||
525 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | 752 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; |
@@ -528,7 +755,8 @@ rest_credential_process_request(struct GNUNET_REST_RequestHandle *conndata_handl | |||
528 | handle->rest_handle = conndata_handle; | 755 | handle->rest_handle = conndata_handle; |
529 | 756 | ||
530 | static const struct GNUNET_REST_RequestHandler handlers[] = { | 757 | static const struct GNUNET_REST_RequestHandler handlers[] = { |
531 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL, &verify_cred_cont}, | 758 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_VERIFY, &verify_cred_cont}, |
759 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_CREDENTIAL_ISSUE, &issue_cred_cont}, | ||
532 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont}, | 760 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_CREDENTIAL, &options_cont}, |
533 | GNUNET_REST_HANDLER_END | 761 | GNUNET_REST_HANDLER_END |
534 | }; | 762 | }; |