1 /****************************************************************************
2  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3  * Copyright (C) 2008-2013 Sourcefire, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License Version 2 as
7  * published by the Free Software Foundation.  You may not use, modify or
8  * distribute this program under any other version of the GNU General
9  * Public License.
10  *
11  * This program 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  ****************************************************************************/
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "stdlib.h"
27 #include "string.h"
28 #include "sf_types.h"
29 #include "sfPolicy.h"
30 #include "sfPolicyUserData.h"
31 
32 /** @defgroup sfPolicyConfig Sourcefire policy configuration module
33  *
34  *  Create a user policy configuration context. A context provides facility for creating
35  *  policy specific data instances. User can create as many policy instances as memory
36  *  resources will allow. User can create/delete context, set/clear/get user date for a
37  *  specific policy, default policy or current policy. User can also iterate over all instances
38  *  user data.
39  *
40  *  In current design, preprocessor use this module directly to manage policy specific data
41  *  instances. A future enhancement can be to extract policy management code from each processor
42  *  and put it in a new policy management module. Policy management module will set a single
43  *  pointer to user data before calling appropriate callback function in a preprocessor. As
44  *  an example, policy module will iterate over all policies and call CleanExit functions in every
45  *  preprocessor for each policy. This will make policy management module will hide policies from
46  *  preprocessors and make them policy agnostic.
47  *  @{
48  */
49 
50 /**Create a user context.
51  * Allocates a new context and return it to user. All transactions within a context are independent from
52  * any other transactions in a different context.
53  *
54  * @returns tSfPolicyUserContextId
55 */
sfPolicyConfigCreate(void)56 tSfPolicyUserContextId sfPolicyConfigCreate(void)
57 {
58     tSfPolicyUserContext *pTmp = NULL;
59 
60     pTmp = calloc(1, sizeof(tSfPolicyUserContext));
61 
62     return pTmp;
63 }
64 
65 /**Delete a user policy data context.
66  * @param pContext
67  */
sfPolicyConfigDelete(tSfPolicyUserContextId pContext)68 void sfPolicyConfigDelete(
69         tSfPolicyUserContextId pContext
70         )
71 {
72     if (pContext == NULL)
73         return;
74 
75     if (pContext->userConfig != NULL)
76         free(pContext->userConfig);
77 
78     free(pContext);
79 }
80 
81 /**Store a pointer to user data.
82  * @param pContext
83  * @param policyId is 0 based.
84  * @param config - pointer to user configuration.
85  */
sfPolicyUserDataSet(tSfPolicyUserContextId pContext,tSfPolicyId policyId,void * config)86 int sfPolicyUserDataSet (
87         tSfPolicyUserContextId pContext,
88         tSfPolicyId policyId,
89         void *config
90         )
91 {
92     void **ppTmp;
93 
94     if (policyId >= pContext->numAllocatedPolicies)
95     {
96         //expand the array
97         ppTmp = (void **)calloc(policyId+POLICY_ALLOCATION_CHUNK, sizeof(void *));
98         if (!(ppTmp))
99         {
100             return -1;
101         }
102 
103         if (pContext->numAllocatedPolicies)
104         {
105             memcpy(ppTmp, pContext->userConfig, sizeof(void*)*(pContext->numAllocatedPolicies));
106             free(pContext->userConfig);
107         }
108 
109         pContext->userConfig = ppTmp;
110         pContext->numAllocatedPolicies = policyId + POLICY_ALLOCATION_CHUNK;
111     }
112 
113     if (pContext->userConfig[policyId])
114     {
115         //dont overwrite existing configuration
116         return -1;
117     }
118 
119     pContext->userConfig[policyId] = config;
120     pContext->numActivePolicies++;
121 
122     return 0;
123 }
124 
125 /**user is responsible for freeing any memory.
126  */
sfPolicyUserDataClear(tSfPolicyUserContextId pContext,tSfPolicyId policyId)127 void * sfPolicyUserDataClear (
128         tSfPolicyUserContextId pContext,
129         tSfPolicyId policyId
130         )
131 {
132     void *pTmp = NULL;
133 
134     if (policyId < pContext->numAllocatedPolicies)
135     {
136         pTmp = pContext->userConfig[policyId];
137         pContext->userConfig[policyId] = NULL;
138         pContext->numActivePolicies--;
139     }
140 
141     return pTmp;
142 }
143 
sfPolicyUserDataIterate(struct _SnortConfig * sc,tSfPolicyUserContextId pContext,int (* callback)(struct _SnortConfig * sc,tSfPolicyUserContextId pContext,tSfPolicyId policyId,void * config))144 int sfPolicyUserDataIterate (
145         struct _SnortConfig *sc,
146         tSfPolicyUserContextId pContext,
147         int (*callback)(struct _SnortConfig *sc, tSfPolicyUserContextId pContext, tSfPolicyId policyId, void* config)
148         )
149 {
150     tSfPolicyId policyId;
151     int ret = 0;
152 
153     //must not use numActivePolicies because the callback may delete a policy
154     for (policyId = 0; policyId < pContext->numAllocatedPolicies; policyId++)
155     {
156         if (pContext->userConfig[policyId])
157         {
158             ret = callback(sc, pContext, policyId, pContext->userConfig[policyId]);
159             if (ret != 0)
160                 break;
161         }
162     }
163 
164     return ret;
165 }
166 
sfPolicyUserDataFreeIterate(tSfPolicyUserContextId pContext,int (* callback)(tSfPolicyUserContextId pContext,tSfPolicyId policyId,void * config))167 int sfPolicyUserDataFreeIterate (
168         tSfPolicyUserContextId pContext,
169         int (*callback)(tSfPolicyUserContextId pContext, tSfPolicyId policyId, void* config)
170         )
171 {
172     tSfPolicyId policyId;
173     int ret = 0;
174 
175     //must not use numActivePolicies because the callback may delete a policy
176     for (policyId = 0; policyId < pContext->numAllocatedPolicies; policyId++)
177     {
178         if (pContext->userConfig[policyId])
179         {
180             ret = callback(pContext, policyId, pContext->userConfig[policyId]);
181             if (ret != 0)
182                 break;
183         }
184     }
185 
186     return ret;
187 }
188 
189 /** @} */ //
190 
191