parse_identityinfo.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * Copyright (c) 2007 iptelorg GmbH
  3. *
  4. * This file is part of ser, a free SIP server.
  5. *
  6. * ser 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 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * ser 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 this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /*! \file
  21. * \brief Parser :: Parse Identity-info header field
  22. *
  23. * \ingroup parser
  24. */
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28. #include "../mem/mem.h"
  29. #include "parse_def.h"
  30. #include "parse_identityinfo.h"
  31. #include "parser_f.h" /* eat_space_end and so on */
  32. /*! \brief Parse Identity-info header field */
  33. void parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b)
  34. {
  35. int status = II_START;
  36. int mainstatus = II_M_START;
  37. char *p;
  38. if (!buffer || !end || !ii_b) return ;
  39. ii_b->error = PARSE_ERROR;
  40. for(p = buffer; p < end; p++) {
  41. switch(*p) {
  42. case '<':
  43. if (status == II_START) {
  44. status=II_URI_BEGIN;
  45. mainstatus = II_M_URI_BEGIN;
  46. ii_b->uri.s = p + 1;
  47. } else
  48. goto parseerror;
  49. break;
  50. case 'h':
  51. case 'H': /* "http://" or "https://" part */
  52. switch (status) {
  53. case II_URI_BEGIN:
  54. if (end - p <= 8 || strncasecmp(p,"http",strlen("http")))
  55. goto parseerror;
  56. p+=4;
  57. if (*p == 's' || *p == 'S') p++;
  58. if (memcmp(p,"://",strlen("://")))
  59. goto parseerror;
  60. p+=2;
  61. status = II_URI_DOMAIN;
  62. break;
  63. case II_URI_DOMAIN:
  64. status = II_URI_IPV4;
  65. case II_URI_IPV4:
  66. case II_URI_IPV6:
  67. case II_URI_PATH:
  68. case II_TOKEN:
  69. case II_TAG:
  70. break;
  71. case II_EQUAL:
  72. status = II_TOKEN;
  73. mainstatus = II_M_TOKEN;
  74. ii_b->alg.s = p;
  75. break;
  76. case II_LWSCRLF:
  77. ii_b->error=PARSE_OK;
  78. return ;
  79. default:
  80. goto parseerror;
  81. }
  82. break;
  83. case '/':
  84. switch(status){
  85. case II_URI_IPV4:
  86. ii_b->domain.len = p - ii_b->domain.s;
  87. status = II_URI_PATH;
  88. break;
  89. case II_URI_PATH:
  90. break;
  91. case II_URI_IPV6:
  92. default:
  93. goto parseerror;
  94. }
  95. break;
  96. case '>':
  97. if (status == II_URI_PATH) {
  98. ii_b->uri.len = p - ii_b->uri.s;
  99. status = II_URI_END;
  100. mainstatus = II_M_URI_END;
  101. } else
  102. goto parseerror;
  103. break;
  104. case ' ':
  105. case '\t':
  106. switch (status) {
  107. case II_EQUAL:
  108. case II_TAG:
  109. case II_SEMIC:
  110. case II_URI_END:
  111. status = II_LWS;
  112. break;
  113. case II_LWS:
  114. case II_LWSCRLFSP:
  115. break;
  116. case II_LWSCRLF:
  117. status = II_LWSCRLFSP;
  118. break;
  119. default:
  120. goto parseerror;
  121. }
  122. break;
  123. case '\r':
  124. switch (status) {
  125. case II_TOKEN:
  126. ii_b->alg.len = p - ii_b->alg.s;
  127. status = II_ENDHEADER;
  128. break;
  129. case II_EQUAL:
  130. case II_TAG:
  131. case II_SEMIC:
  132. case II_URI_END:
  133. case II_LWS:
  134. status = II_LWSCR;
  135. break;
  136. case II_LWSCRLF:
  137. ii_b->error=PARSE_OK;
  138. return ;
  139. default:
  140. goto parseerror;
  141. }
  142. break;
  143. case '\n':
  144. switch (status) {
  145. case II_LWSCRLF:
  146. ii_b->error=PARSE_OK;
  147. return ;
  148. case II_EQUAL:
  149. case II_TAG:
  150. case II_SEMIC:
  151. case II_URI_END:
  152. case II_LWS:
  153. case II_LWSCR:
  154. status = II_LWSCRLF;
  155. break;
  156. case II_TOKEN: /* if there was not '\r' */
  157. ii_b->alg.len = p - ii_b->alg.s;
  158. case II_ENDHEADER:
  159. p=eat_lws_end(p, end);
  160. /*check if the header ends here*/
  161. if (p>=end) {
  162. LOG(L_ERR, "ERROR: parse_identityinfo: strange EoHF\n");
  163. goto parseerror;
  164. }
  165. ii_b->error=PARSE_OK;
  166. return ;
  167. default:
  168. goto parseerror;
  169. }
  170. break;
  171. case ';':
  172. switch (status) {
  173. case II_URI_END:
  174. case II_LWS:
  175. case II_LWSCRLFSP:
  176. if (mainstatus == II_M_URI_END) {
  177. status = II_SEMIC;
  178. mainstatus = II_M_SEMIC;
  179. } else
  180. goto parseerror;
  181. break;
  182. default:
  183. goto parseerror;
  184. }
  185. break;
  186. case 'a': /* tag part of 'alg' parameter */
  187. case 'A':
  188. switch (status) {
  189. case II_LWS:
  190. case II_LWSCRLFSP:
  191. case II_SEMIC:
  192. if (mainstatus == II_M_SEMIC) {
  193. mainstatus = II_M_TAG;
  194. status = II_TAG;
  195. if (end - p <= 3 || strncasecmp(p,"alg",strlen("alg")))
  196. goto parseerror;
  197. p+=2;
  198. } else
  199. goto parseerror;
  200. break;
  201. case II_URI_DOMAIN:
  202. status = II_URI_IPV4;
  203. case II_URI_IPV4:
  204. case II_URI_IPV6:
  205. case II_URI_PATH:
  206. case II_TOKEN:
  207. break;
  208. case II_EQUAL:
  209. status = II_TOKEN;
  210. mainstatus = II_M_TOKEN;
  211. ii_b->alg.s = p;
  212. break;
  213. case II_LWSCRLF:
  214. ii_b->error=PARSE_OK;
  215. return ;
  216. default:
  217. goto parseerror;
  218. }
  219. break;
  220. case '=':
  221. switch (status) {
  222. case II_TAG:
  223. case II_LWS:
  224. case II_LWSCRLFSP:
  225. if (mainstatus == II_M_TAG) {
  226. status = II_EQUAL;
  227. mainstatus = II_M_EQUAL;
  228. } else
  229. goto parseerror;
  230. break;
  231. case II_URI_PATH:
  232. break;
  233. default:
  234. goto parseerror;
  235. }
  236. break;
  237. case '[':
  238. switch (status) {
  239. case II_URI_DOMAIN:
  240. status = II_URI_IPV6;
  241. ii_b->domain.s = p + 1;
  242. break;
  243. default:
  244. goto parseerror;
  245. }
  246. break;
  247. case ']':
  248. switch (status) {
  249. case II_URI_IPV6:
  250. ii_b->domain.len = p - ii_b->domain.s;
  251. status = II_URI_PATH;
  252. break;
  253. case II_URI_IPV4:
  254. case II_URI_PATH:
  255. goto parseerror;
  256. }
  257. break;
  258. case ':':
  259. if (status == II_URI_IPV4) {
  260. ii_b->domain.len = p - ii_b->domain.s;
  261. status = II_URI_PATH;
  262. }
  263. break;
  264. default:
  265. switch (status) {
  266. case II_EQUAL:
  267. case II_LWS:
  268. case II_LWSCRLFSP:
  269. if (mainstatus == II_M_EQUAL) {
  270. status = II_TOKEN;
  271. mainstatus = II_M_TOKEN;
  272. ii_b->alg.s = p;
  273. } else
  274. goto parseerror;
  275. break;
  276. case II_TOKEN:
  277. break;
  278. case II_LWSCRLF:
  279. ii_b->error=PARSE_OK;
  280. return ;
  281. case II_URI_DOMAIN:
  282. ii_b->domain.s = p;
  283. status = II_URI_IPV4;
  284. case II_URI_IPV4:
  285. case II_URI_IPV6:
  286. if (isalnum(*p)
  287. || *p == '-'
  288. || *p == '.'
  289. || *p == ':' )
  290. break;
  291. case II_START:
  292. goto parseerror;
  293. }
  294. break;
  295. }
  296. }
  297. /* we successfully parse the header */
  298. ii_b->error=PARSE_OK;
  299. return ;
  300. parseerror:
  301. LOG( L_ERR , "ERROR: parse_identityinfo: "
  302. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  303. *p,status, (int)(p-buffer), ZSW(p));
  304. return ;
  305. }
  306. int parse_identityinfo_header(struct sip_msg *msg)
  307. {
  308. struct identityinfo_body* identityinfo_b;
  309. if ( !msg->identity_info
  310. && (parse_headers(msg,HDR_IDENTITY_INFO_F,0)==-1
  311. || !msg->identity_info) ) {
  312. LOG(L_ERR,"ERROR:parse_identityinfo_header: bad msg or missing IDENTITY-INFO header\n");
  313. goto error;
  314. }
  315. /* maybe the header is already parsed! */
  316. if (msg->identity_info->parsed)
  317. return 0;
  318. identityinfo_b=pkg_malloc(sizeof(*identityinfo_b));
  319. if (identityinfo_b==0){
  320. LOG(L_ERR, "ERROR:parse_identityinfo_header: out of memory\n");
  321. goto error;
  322. }
  323. memset(identityinfo_b, 0, sizeof(*identityinfo_b));
  324. parse_identityinfo(msg->identity_info->body.s,
  325. msg->identity_info->body.s + msg->identity_info->body.len+1,
  326. identityinfo_b);
  327. if (identityinfo_b->error==PARSE_ERROR){
  328. free_identityinfo(identityinfo_b);
  329. goto error;
  330. }
  331. msg->identity_info->parsed=(void*)identityinfo_b;
  332. return 0;
  333. error:
  334. return -1;
  335. }
  336. void free_identityinfo(struct identityinfo_body *ii_b)
  337. {
  338. pkg_free(ii_b);
  339. }