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(&copy, 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