thttp_parser_header_WWW_Authenticate.rl 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * Copyright (C) 2010-2015 Mamadou Diop.
  3. *
  4. * This file is part of Open Source Doubango Framework.
  5. *
  6. * DOUBANGO is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * DOUBANGO is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with DOUBANGO.
  18. *
  19. */
  20. /**@file thttp_header_WWW_Authenticate.c
  21. * @brief HTTP WWW-Authenticate header.
  22. */
  23. #include "tinyhttp/headers/thttp_header_WWW_Authenticate.h"
  24. #include "tinyhttp/parsers/thttp_parser_url.h"
  25. #include "tsk_debug.h"
  26. #include "tsk_memory.h"
  27. #include "tsk_time.h"
  28. #include <string.h>
  29. // Check if we have ",CRLF" ==> See WWW-Authenticate header
  30. // As :>CRLF is preceded by any+ ==> p will be at least (start + 1)
  31. // p point to CR
  32. #define prev_not_comma(p) !(p && p[-1] == ',')
  33. /***********************************
  34. * Ragel state machine.
  35. */
  36. %%{
  37. machine thttp_machine_parser_header_WWW_Authenticate;
  38. # Includes
  39. include thttp_machine_utils "./ragel/thttp_machine_utils.rl";
  40. action tag{
  41. tag_start = p;
  42. }
  43. action is_digest{
  44. hdr_WWW_Authenticate->scheme = tsk_strdup("Digest");
  45. }
  46. action is_basic{
  47. hdr_WWW_Authenticate->scheme = tsk_strdup("Basic");
  48. }
  49. action is_auth{
  50. THTTP_HEADER(hdr_WWW_Authenticate)->type = thttp_htype_WWW_Authenticate;
  51. }
  52. action is_proxy{
  53. THTTP_HEADER(hdr_WWW_Authenticate)->type = thttp_htype_Proxy_Authenticate;
  54. }
  55. action parse_realm{
  56. TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->realm);
  57. tsk_strunquote(&hdr_WWW_Authenticate->realm);
  58. }
  59. action parse_domain{
  60. TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->domain);
  61. //tsk_strunquote(&hdr_WWW_Authenticate->domain);
  62. }
  63. action parse_nonce{
  64. TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->nonce);
  65. tsk_strunquote(&hdr_WWW_Authenticate->nonce);
  66. }
  67. action parse_opaque{
  68. TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->opaque);
  69. tsk_strunquote(&hdr_WWW_Authenticate->opaque);
  70. }
  71. action parse_stale{
  72. hdr_WWW_Authenticate->stale = tsk_strniequals(tag_start, "true", 4);
  73. }
  74. action parse_algorithm{
  75. TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->algorithm);
  76. }
  77. action parse_qop{
  78. TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->qop);
  79. //tsk_strunquote(&hdr_WWW_Authenticate->qop);
  80. }
  81. action parse_param{
  82. TSK_PARSER_ADD_PARAM(THTTP_HEADER_PARAMS(hdr_WWW_Authenticate));
  83. }
  84. action prev_not_comma{
  85. prev_not_comma(p)
  86. }
  87. action eob{
  88. }
  89. #FIXME: Only Digest (MD5, AKAv1-MD5 and AKAv2-MD5) is supported
  90. other_challenge = (any+);
  91. auth_param = generic_param>tag %parse_param;
  92. realm = "realm"i EQUAL quoted_string>tag %parse_realm;
  93. domain = "domain"i EQUAL LDQUOT <: (any*)>tag %parse_domain :> RDQUOT;
  94. nonce = "nonce"i EQUAL quoted_string>tag %parse_nonce;
  95. opaque = "opaque"i EQUAL quoted_string>tag %parse_opaque;
  96. stale = "stale"i EQUAL ( "true"i | "false"i )>tag %parse_stale;
  97. algorithm = "algorithm"i EQUAL <:token>tag %parse_algorithm;
  98. qop_options = "qop"i EQUAL LDQUOT <: (any*)>tag %parse_qop :> RDQUOT;
  99. digest_cln = (realm | domain | nonce | opaque | stale | algorithm | qop_options)@1 | auth_param@0;
  100. challenge = ( ("Digest"i%is_digest | "Basic"i%is_basic) LWS digest_cln ( (COMMA | CRLF) <:digest_cln )* ) | other_challenge;
  101. WWW_Authenticate = ("WWW-Authenticate"i>is_auth | "Proxy-Authenticate"i>is_proxy) HCOLON challenge;
  102. # Entry point
  103. main := WWW_Authenticate CRLF @eob;
  104. }%%
  105. thttp_header_WWW_Authenticate_t* thttp_header_www_authenticate_create()
  106. {
  107. return tsk_object_new(thttp_header_WWW_Authenticate_def_t);
  108. }
  109. int thttp_header_WWW_Authenticate_tostring(const thttp_header_t* header, tsk_buffer_t* output)
  110. {
  111. if(header){
  112. const thttp_header_WWW_Authenticate_t *WWW_Authenticate = (const thttp_header_WWW_Authenticate_t*)header;
  113. if(WWW_Authenticate && WWW_Authenticate->scheme){
  114. return tsk_buffer_append_2(output, "%s realm=\"%s\"%s%s%s%s%s%s%s%s%s%s%s%s,stale=%s%s%s",
  115. WWW_Authenticate->scheme,
  116. WWW_Authenticate->realm ? WWW_Authenticate->realm : "",
  117. WWW_Authenticate->domain ? ",domain=\"" : "",
  118. WWW_Authenticate->domain ? WWW_Authenticate->domain : "",
  119. WWW_Authenticate->domain ? "\"" : "",
  120. WWW_Authenticate->qop ? ",qop=\"" : "",
  121. WWW_Authenticate->qop ? WWW_Authenticate->qop : "",
  122. WWW_Authenticate->qop ? "\"" : "",
  123. WWW_Authenticate->nonce ? ",nonce=\"" : "",
  124. WWW_Authenticate->nonce ? WWW_Authenticate->nonce : "",
  125. WWW_Authenticate->nonce ? "\"" : "",
  126. WWW_Authenticate->opaque ? ",opaque=\"" : "",
  127. WWW_Authenticate->opaque ? WWW_Authenticate->opaque : "",
  128. WWW_Authenticate->opaque ? "\"" : "",
  129. WWW_Authenticate->stale ? "TRUE" : "FALSE",
  130. WWW_Authenticate->algorithm ? ",algorithm=" : "",
  131. WWW_Authenticate->algorithm ? WWW_Authenticate->algorithm : ""
  132. );
  133. }
  134. }
  135. return -1;
  136. }
  137. /**@ingroup thttp_header_group
  138. */
  139. thttp_header_WWW_Authenticate_t *thttp_header_WWW_Authenticate_parse(const char *data, tsk_size_t size)
  140. {
  141. int cs = 0;
  142. const char *p = data;
  143. const char *pe = p + size;
  144. const char *eof = pe;
  145. thttp_header_WWW_Authenticate_t *hdr_WWW_Authenticate = thttp_header_www_authenticate_create();
  146. const char *tag_start = tsk_null;
  147. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  148. %%write data;
  149. (void)(eof);
  150. (void)(thttp_machine_parser_header_WWW_Authenticate_first_final);
  151. (void)(thttp_machine_parser_header_WWW_Authenticate_error);
  152. (void)(thttp_machine_parser_header_WWW_Authenticate_en_main);
  153. %%write init;
  154. %%write exec;
  155. TSK_RAGEL_DISABLE_WARNINGS_END()
  156. if( cs < %%{ write first_final; }%% ){
  157. TSK_DEBUG_ERROR("Failed to parse WWW-Authenticate header.");
  158. TSK_OBJECT_SAFE_FREE(hdr_WWW_Authenticate);
  159. }
  160. return hdr_WWW_Authenticate;
  161. }
  162. thttp_header_Proxy_Authenticate_t *thttp_header_Proxy_Authenticate_parse(const char *data, tsk_size_t size)
  163. {
  164. return thttp_header_WWW_Authenticate_parse(data, size);
  165. }
  166. //========================================================
  167. // WWW_Authenticate header object definition
  168. //
  169. static tsk_object_t* thttp_header_WWW_Authenticate_ctor(tsk_object_t *self, va_list * app)
  170. {
  171. thttp_header_WWW_Authenticate_t *WWW_Authenticate = self;
  172. if(WWW_Authenticate){
  173. THTTP_HEADER(WWW_Authenticate)->type = thttp_htype_WWW_Authenticate;
  174. THTTP_HEADER(WWW_Authenticate)->tostring = thttp_header_WWW_Authenticate_tostring;
  175. }
  176. else{
  177. TSK_DEBUG_ERROR("Failed to create new WWW_Authenticate header.");
  178. }
  179. return self;
  180. }
  181. static tsk_object_t* thttp_header_WWW_Authenticate_dtor(tsk_object_t *self)
  182. {
  183. thttp_header_WWW_Authenticate_t *WWW_Authenticate = self;
  184. if(WWW_Authenticate){
  185. TSK_FREE(WWW_Authenticate->scheme);
  186. TSK_FREE(WWW_Authenticate->realm);
  187. TSK_FREE(WWW_Authenticate->domain);
  188. TSK_FREE(WWW_Authenticate->nonce);
  189. TSK_FREE(WWW_Authenticate->opaque);
  190. TSK_FREE(WWW_Authenticate->algorithm);
  191. TSK_FREE(WWW_Authenticate->qop);
  192. TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(WWW_Authenticate));
  193. }
  194. else{
  195. TSK_DEBUG_ERROR("Null WWW_Authenticate header.");
  196. }
  197. return self;
  198. }
  199. static const tsk_object_def_t thttp_header_WWW_Authenticate_def_s =
  200. {
  201. sizeof(thttp_header_WWW_Authenticate_t),
  202. thttp_header_WWW_Authenticate_ctor,
  203. thttp_header_WWW_Authenticate_dtor,
  204. tsk_null
  205. };
  206. const tsk_object_def_t *thttp_header_WWW_Authenticate_def_t = &thttp_header_WWW_Authenticate_def_s;