1 /***************************************************************************
2 * Copyright (c) 2009-2010 Open Information Security Foundation
3 * Copyright (c) 2010-2013 Qualys, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16
17 * - Neither the name of the Qualys, Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 ***************************************************************************/
33
34 /**
35 * @file
36 * @author Ivan Ristic <ivanr@webkreator.com>
37 */
38
39 #include "htp_config_auto.h"
40
41 #include "htp_private.h"
42
htp_hook_copy(const htp_hook_t * hook)43 htp_hook_t *htp_hook_copy(const htp_hook_t *hook) {
44 if (hook == NULL) return NULL;
45
46 htp_hook_t *copy = htp_hook_create();
47 if (copy == NULL) return NULL;
48
49 for (size_t i = 0, n = htp_list_size(hook->callbacks); i < n; i++) {
50 htp_callback_t *callback = htp_list_get(hook->callbacks, i);
51 if (htp_hook_register(©, callback->fn) != HTP_OK) {
52 htp_hook_destroy(copy);
53 return NULL;
54 }
55 }
56
57 return copy;
58 }
59
htp_hook_create(void)60 htp_hook_t *htp_hook_create(void) {
61 htp_hook_t *hook = calloc(1, sizeof (htp_hook_t));
62 if (hook == NULL) return NULL;
63
64 hook->callbacks = (htp_list_array_t *) htp_list_array_create(4);
65 if (hook->callbacks == NULL) {
66 free(hook);
67 return NULL;
68 }
69
70 return hook;
71 }
72
htp_hook_destroy(htp_hook_t * hook)73 void htp_hook_destroy(htp_hook_t *hook) {
74 if (hook == NULL) return;
75
76 for (size_t i = 0, n = htp_list_size(hook->callbacks); i < n; i++) {
77 free((htp_callback_t *) htp_list_get(hook->callbacks, i));
78 }
79
80 htp_list_array_destroy(hook->callbacks);
81
82 free(hook);
83 }
84
htp_hook_register(htp_hook_t ** hook,const htp_callback_fn_t callback_fn)85 htp_status_t htp_hook_register(htp_hook_t **hook, const htp_callback_fn_t callback_fn) {
86 if (hook == NULL) return HTP_ERROR;
87
88 htp_callback_t *callback = calloc(1, sizeof (htp_callback_t));
89 if (callback == NULL) return HTP_ERROR;
90
91 callback->fn = callback_fn;
92
93 // Create a new hook if one does not exist
94 int hook_created = 0;
95
96 if (*hook == NULL) {
97 hook_created = 1;
98
99 *hook = htp_hook_create();
100 if (*hook == NULL) {
101 free(callback);
102 return HTP_ERROR;
103 }
104 }
105
106 // Add callback
107 if (htp_list_array_push((*hook)->callbacks, callback) != HTP_OK) {
108 if (hook_created) {
109 free(*hook);
110 }
111
112 free(callback);
113
114 return HTP_ERROR;
115 }
116
117 return HTP_OK;
118 }
119
htp_hook_run_all(htp_hook_t * hook,void * user_data)120 htp_status_t htp_hook_run_all(htp_hook_t *hook, void *user_data) {
121 if (hook == NULL) return HTP_OK;
122
123 // Loop through the registered callbacks, giving each a chance to run.
124 for (size_t i = 0, n = htp_list_size(hook->callbacks); i < n; i++) {
125 htp_callback_t *callback = htp_list_get(hook->callbacks, i);
126
127 htp_status_t rc = callback->fn(user_data);
128
129 // A hook can return HTP_OK to say that it did some work,
130 // or HTP_DECLINED to say that it did no work. Anything else
131 // is treated as an error.
132 if ((rc != HTP_OK) && (rc != HTP_DECLINED)) {
133 return rc;
134 }
135 }
136
137 return HTP_OK;
138 }
139
htp_hook_run_one(htp_hook_t * hook,void * user_data)140 htp_status_t htp_hook_run_one(htp_hook_t *hook, void *user_data) {
141 if (hook == NULL) return HTP_DECLINED;
142
143 for (size_t i = 0, n = htp_list_size(hook->callbacks); i < n; i++) {
144 htp_callback_t *callback = htp_list_get(hook->callbacks, i);
145
146 htp_status_t rc = callback->fn(user_data);
147
148 // A hook can return HTP_DECLINED to say that it did no work,
149 // and we'll ignore that. If we see HTP_OK or anything else,
150 // we stop processing (because it was either a successful
151 // handling or an error).
152 if (rc != HTP_DECLINED) {
153 // Return HTP_OK or an error.
154 return rc;
155 }
156 }
157
158 // No hook wanted to process the callback.
159 return HTP_DECLINED;
160 }
161