diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2012-09-20 08:55:20 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2012-09-20 08:55:20 +0000 |
commit | 37c4704049df39026b5fb043bcebcd7a15ecf1a2 (patch) | |
tree | 63715573fa07c05d7ff393462f0ce986adca9d85 /src | |
parent | f1be2c0c8410b0829171990f85ffb4d107216ffb (diff) | |
download | gnunet-37c4704049df39026b5fb043bcebcd7a15ecf1a2.tar.gz gnunet-37c4704049df39026b5fb043bcebcd7a15ecf1a2.zip |
- url parsing
Diffstat (limited to 'src')
-rw-r--r-- | src/transport/plugin_transport_http_server.c | 235 |
1 files changed, 125 insertions, 110 deletions
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c index e8250af8b..c674a6755 100644 --- a/src/transport/plugin_transport_http_server.c +++ b/src/transport/plugin_transport_http_server.c | |||
@@ -221,6 +221,11 @@ struct HTTP_Server_Plugin | |||
221 | int in_shutdown; | 221 | int in_shutdown; |
222 | 222 | ||
223 | /** | 223 | /** |
224 | * Length of peer id | ||
225 | */ | ||
226 | int peer_id_length; | ||
227 | |||
228 | /** | ||
224 | * External hostname the plugin can be connected to, can be different to | 229 | * External hostname the plugin can be connected to, can be different to |
225 | * the host's FQDN, used e.g. for reverse proxying | 230 | * the host's FQDN, used e.g. for reverse proxying |
226 | */ | 231 | */ |
@@ -844,6 +849,112 @@ server_mhd_connection_timeout (struct HTTP_Server_Plugin *plugin, struct Session | |||
844 | #endif | 849 | #endif |
845 | } | 850 | } |
846 | 851 | ||
852 | /** | ||
853 | * Parse incoming URL for tag and target | ||
854 | * | ||
855 | * @url incoming url | ||
856 | * @target where to store the target | ||
857 | * @tag where to store the tag | ||
858 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
859 | */ | ||
860 | |||
861 | static int | ||
862 | server_parse_url (struct HTTP_Server_Plugin *plugin, const char * url, struct GNUNET_PeerIdentity * target, uint32_t *tag) | ||
863 | { | ||
864 | int debug = GNUNET_YES; | ||
865 | |||
866 | char * tag_start = NULL; | ||
867 | char * tag_end = NULL; | ||
868 | char * target_start = NULL; | ||
869 | char * separator = NULL; | ||
870 | char hash[plugin->peer_id_length+1]; | ||
871 | int hash_length; | ||
872 | |||
873 | /* URL parsing | ||
874 | * URL is valid if it is in the form [prefix with (multiple) '/'][peerid[103];tag]*/ | ||
875 | |||
876 | if (NULL == url) | ||
877 | { | ||
878 | GNUNET_break (0); | ||
879 | return GNUNET_SYSERR; | ||
880 | } | ||
881 | /* convert tag */ | ||
882 | |||
883 | /* find separator */ | ||
884 | separator = strrchr (url, ';'); | ||
885 | |||
886 | if (NULL == separator) | ||
887 | { | ||
888 | if (debug) GNUNET_break (0); | ||
889 | return GNUNET_SYSERR; | ||
890 | } | ||
891 | tag_start = separator + 1; | ||
892 | |||
893 | if (strlen (tag_start) == 0) | ||
894 | { | ||
895 | /* No tag after separator */ | ||
896 | if (debug) GNUNET_break (0); | ||
897 | return GNUNET_SYSERR; | ||
898 | } | ||
899 | (*tag) = strtoul (tag_start, &tag_end, 10); | ||
900 | if ((*tag) == 0) | ||
901 | { | ||
902 | /* tag == 0 , invalid */ | ||
903 | if (debug) GNUNET_break (0); | ||
904 | return GNUNET_SYSERR; | ||
905 | } | ||
906 | if (((*tag) == ULONG_MAX) && (ERANGE == errno)) | ||
907 | { | ||
908 | /* out of range: > ULONG_MAX */ | ||
909 | if (debug) GNUNET_break (0); | ||
910 | return GNUNET_SYSERR; | ||
911 | } | ||
912 | if (NULL == tag_end) | ||
913 | { | ||
914 | /* no char after tag */ | ||
915 | if (debug) GNUNET_break (0); | ||
916 | return GNUNET_SYSERR; | ||
917 | } | ||
918 | if (url[strlen(url)] != tag_end[0]) | ||
919 | { | ||
920 | /* there are more not converted chars after tag */ | ||
921 | if (debug) GNUNET_break (0); | ||
922 | return GNUNET_SYSERR; | ||
923 | } | ||
924 | if (debug) | ||
925 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
926 | "Found tag `%u' in url\n", (*tag)); | ||
927 | |||
928 | /* convert peer id */ | ||
929 | target_start = strrchr (url, '/'); | ||
930 | if (NULL == target_start) | ||
931 | { | ||
932 | /* no leading '/' */ | ||
933 | target_start = url; | ||
934 | } | ||
935 | target_start++; | ||
936 | hash_length = separator - target_start; | ||
937 | if (hash_length != plugin->peer_id_length) | ||
938 | { | ||
939 | /* no char after tag */ | ||
940 | if (debug) GNUNET_break (0); | ||
941 | return GNUNET_SYSERR; | ||
942 | } | ||
943 | memcpy (hash, target_start, hash_length); | ||
944 | hash[hash_length] = '\0'; | ||
945 | |||
946 | if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((const char *) hash, &(target->hashPubKey))) | ||
947 | { | ||
948 | /* hash conversion failed */ | ||
949 | if (debug) GNUNET_break (0); | ||
950 | return GNUNET_SYSERR; | ||
951 | } | ||
952 | |||
953 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
954 | "Found target `%s' in url\n", GNUNET_h2s_full(&target->hashPubKey)); | ||
955 | return GNUNET_OK; | ||
956 | } | ||
957 | |||
847 | 958 | ||
848 | /** | 959 | /** |
849 | * Lookup a mhd connection and create one if none is found | 960 | * Lookup a mhd connection and create one if none is found |
@@ -872,14 +983,6 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
872 | int direction = GNUNET_SYSERR; | 983 | int direction = GNUNET_SYSERR; |
873 | int to; | 984 | int to; |
874 | 985 | ||
875 | /* url parsing variables */ | ||
876 | size_t url_len; | ||
877 | char *url_end; | ||
878 | char *hash_start; | ||
879 | char *hash_end; | ||
880 | char *tag_start; | ||
881 | char *tag_end; | ||
882 | |||
883 | conn_info = MHD_get_connection_info (mhd_connection, | 986 | conn_info = MHD_get_connection_info (mhd_connection, |
884 | MHD_CONNECTION_INFO_CLIENT_ADDRESS); | 987 | MHD_CONNECTION_INFO_CLIENT_ADDRESS); |
885 | if ((conn_info->client_addr->sa_family != AF_INET) && | 988 | if ((conn_info->client_addr->sa_family != AF_INET) && |
@@ -888,104 +991,21 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
888 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | 991 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
889 | "New %s connection from %s\n", method, url); | 992 | "New %s connection from %s\n", method, url); |
890 | 993 | ||
891 | /* URL parsing | 994 | if (GNUNET_SYSERR == server_parse_url (plugin, url, &target, &tag)) |
892 | * URL is valid if it is in the form [peerid[103];tag]*/ | ||
893 | url_len = strlen (url); | ||
894 | url_end = (char *) &url[url_len]; | ||
895 | |||
896 | if (url_len < 105) | ||
897 | { | ||
898 | |||
899 | goto error; /* too short */ | ||
900 | } | ||
901 | hash_start = strrchr (url, '/'); | ||
902 | if (NULL == hash_start) | ||
903 | { | ||
904 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
905 | "Invalid request with url `%s': %s\n", url, "No delimiter found"); | ||
906 | goto error; /* '/' delimiter not found */ | ||
907 | } | ||
908 | if (hash_start >= url_end) | ||
909 | { | 995 | { |
910 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | 996 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
911 | "Invalid request with url `%s': %s\n", url, "Malformed delimiter"); | 997 | "Invalid url %s\n", url); |
912 | goto error; /* mal formed */ | 998 | return NULL; |
913 | } | ||
914 | hash_start++; | ||
915 | |||
916 | hash_end = strrchr (hash_start, ';'); | ||
917 | if (NULL == hash_end) | ||
918 | { | ||
919 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
920 | "Invalid request with url `%s': %s\n", url, "No `;' delimiter found"); | ||
921 | goto error; /* ';' delimiter not found */ | ||
922 | } | ||
923 | |||
924 | if (hash_end >= url_end) | ||
925 | { | ||
926 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
927 | "Invalid request with url `%s': %s\n", url, "Malformed length"); | ||
928 | goto error; /* mal formed */ | ||
929 | } | ||
930 | |||
931 | if (hash_start >= hash_end) | ||
932 | { | ||
933 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
934 | "Invalid request with url `%s': %s\n", url, "Malformed length"); | ||
935 | goto error; /* mal formed */ | ||
936 | } | ||
937 | |||
938 | if ((strlen(hash_start) - strlen(hash_end)) != 103) | ||
939 | { | ||
940 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
941 | "New %s connection from %s\n", method, url); | ||
942 | goto error; /* invalid hash length */ | ||
943 | } | ||
944 | |||
945 | char hash[104]; | ||
946 | memcpy (hash, hash_start, 103); | ||
947 | hash[103] = '\0'; | ||
948 | if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((const char *) hash, &(target.hashPubKey))) | ||
949 | { | ||
950 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
951 | "Invalid request with url `%s': %s\n", url, "Malformed peer id"); | ||
952 | goto error; /* mal formed */ | ||
953 | } | ||
954 | |||
955 | if (hash_end >= url_end) | ||
956 | { | ||
957 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
958 | "Invalid request with url `%s': %s\n", url, "Malformed length"); | ||
959 | goto error; /* mal formed */ | ||
960 | } | ||
961 | |||
962 | tag_start = &hash_end[1]; | ||
963 | /* Converting tag */ | ||
964 | tag_end = NULL; | ||
965 | tag = strtoul (tag_start, &tag_end, 10); | ||
966 | if (tag == 0) | ||
967 | { | ||
968 | GNUNET_break (0); | ||
969 | goto error; /* mal formed */ | ||
970 | } | ||
971 | if (tag_end == NULL) | ||
972 | { | ||
973 | GNUNET_break (0); | ||
974 | goto error; /* mal formed */ | ||
975 | } | ||
976 | if (tag_end != url_end) | ||
977 | { | ||
978 | GNUNET_break (0); | ||
979 | goto error; /* mal formed */ | ||
980 | } | 999 | } |
981 | |||
982 | if (0 == strcmp (MHD_HTTP_METHOD_PUT, method)) | 1000 | if (0 == strcmp (MHD_HTTP_METHOD_PUT, method)) |
983 | direction = _RECEIVE; | 1001 | direction = _RECEIVE; |
984 | else if (0 == strcmp (MHD_HTTP_METHOD_GET, method)) | 1002 | else if (0 == strcmp (MHD_HTTP_METHOD_GET, method)) |
985 | direction = _SEND; | 1003 | direction = _SEND; |
986 | else | 1004 | else |
987 | { | 1005 | { |
988 | goto error; | 1006 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
1007 | "Invalid method %s connection from %s\n", method, url); | ||
1008 | return NULL; | ||
989 | } | 1009 | } |
990 | 1010 | ||
991 | plugin->cur_connections++; | 1011 | plugin->cur_connections++; |
@@ -994,7 +1014,6 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
994 | method, | 1014 | method, |
995 | GNUNET_i2s (&target), tag, | 1015 | GNUNET_i2s (&target), tag, |
996 | plugin->cur_connections, plugin->max_connections); | 1016 | plugin->cur_connections, plugin->max_connections); |
997 | |||
998 | /* find duplicate session */ | 1017 | /* find duplicate session */ |
999 | s = plugin->head; | 1018 | s = plugin->head; |
1000 | while (s != NULL) | 1019 | while (s != NULL) |
@@ -1012,7 +1031,8 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1012 | "Duplicate PUT connection from `%s' tag %u, dismissing new connection\n", | 1031 | "Duplicate PUT connection from `%s' tag %u, dismissing new connection\n", |
1013 | GNUNET_i2s (&target), | 1032 | GNUNET_i2s (&target), |
1014 | tag); | 1033 | tag); |
1015 | goto error; | 1034 | return NULL; |
1035 | |||
1016 | } | 1036 | } |
1017 | if ((_SEND == direction) && (NULL != s->server_send)) | 1037 | if ((_SEND == direction) && (NULL != s->server_send)) |
1018 | { | 1038 | { |
@@ -1020,7 +1040,7 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1020 | "Duplicate GET connection from `%s' tag %u, dismissing new connection\n", | 1040 | "Duplicate GET connection from `%s' tag %u, dismissing new connection\n", |
1021 | GNUNET_i2s (&target), | 1041 | GNUNET_i2s (&target), |
1022 | tag); | 1042 | tag); |
1023 | goto error; | 1043 | return NULL; |
1024 | } | 1044 | } |
1025 | } | 1045 | } |
1026 | else | 1046 | else |
@@ -1040,9 +1060,8 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1040 | break; | 1060 | break; |
1041 | default: | 1061 | default: |
1042 | GNUNET_break (0); | 1062 | GNUNET_break (0); |
1043 | goto error; | 1063 | return NULL; |
1044 | } | 1064 | } |
1045 | |||
1046 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | 1065 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
1047 | "Creating new session for peer `%s' connecting from `%s'\n", | 1066 | "Creating new session for peer `%s' connecting from `%s'\n", |
1048 | GNUNET_i2s (&target), | 1067 | GNUNET_i2s (&target), |
@@ -1063,7 +1082,6 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1063 | server_start_session_timeout(s); | 1082 | server_start_session_timeout(s); |
1064 | GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); | 1083 | GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); |
1065 | } | 1084 | } |
1066 | |||
1067 | sc = GNUNET_malloc (sizeof (struct ServerConnection)); | 1085 | sc = GNUNET_malloc (sizeof (struct ServerConnection)); |
1068 | if (conn_info->client_addr->sa_family == AF_INET) | 1086 | if (conn_info->client_addr->sa_family == AF_INET) |
1069 | sc->mhd_daemon = plugin->server_v4; | 1087 | sc->mhd_daemon = plugin->server_v4; |
@@ -1077,7 +1095,6 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1077 | s->server_send = sc; | 1095 | s->server_send = sc; |
1078 | if (direction == _RECEIVE) | 1096 | if (direction == _RECEIVE) |
1079 | s->server_recv = sc; | 1097 | s->server_recv = sc; |
1080 | |||
1081 | #if MHD_VERSION >= 0x00090E00 | 1098 | #if MHD_VERSION >= 0x00090E00 |
1082 | if ((NULL == s->server_recv) || (NULL == s->server_send)) | 1099 | if ((NULL == s->server_recv) || (NULL == s->server_send)) |
1083 | { | 1100 | { |
@@ -1098,12 +1115,6 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1098 | "Setting timeout for %p to %u sec.\n", sc, to); | 1115 | "Setting timeout for %p to %u sec.\n", sc, to); |
1099 | #endif | 1116 | #endif |
1100 | return sc; | 1117 | return sc; |
1101 | |||
1102 | /* Error condition */ | ||
1103 | error: | ||
1104 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | ||
1105 | "Invalid connection request\n"); | ||
1106 | return NULL; | ||
1107 | } | 1118 | } |
1108 | 1119 | ||
1109 | 1120 | ||
@@ -2692,6 +2703,10 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin) | |||
2692 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, | 2703 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, |
2693 | _("Maximum number of connections is %u\n"), | 2704 | _("Maximum number of connections is %u\n"), |
2694 | plugin->max_connections); | 2705 | plugin->max_connections); |
2706 | |||
2707 | |||
2708 | plugin->peer_id_length = strlen (GNUNET_h2s_full (&plugin->env->my_identity->hashPubKey)); | ||
2709 | |||
2695 | return GNUNET_OK; | 2710 | return GNUNET_OK; |
2696 | } | 2711 | } |
2697 | 2712 | ||