Revert "Remove TPCS and TWPServer features"
[platform/upstream/csf-framework.git] / framework / TCSImpl.c
1 /*
2     Copyright (c) 2014, McAfee, Inc.
3     
4     All rights reserved.
5     
6     Redistribution and use in source and binary forms, with or without modification,
7     are permitted provided that the following conditions are met:
8     
9     Redistributions of source code must retain the above copyright notice, this list
10     of conditions and the following disclaimer.
11     
12     Redistributions in binary form must reproduce the above copyright notice, this
13     list of conditions and the following disclaimer in the documentation and/or other
14     materials provided with the distribution.
15     
16     Neither the name of McAfee, Inc. nor the names of its contributors may be used
17     to endorse or promote products derived from this software without specific prior
18     written permission.
19     
20     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23     IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28     OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29     OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <dlfcn.h>
35 #include <malloc.h>
36 #include <pthread.h>
37 #include <string.h>
38
39 #include "Debug.h"
40 #include "TCSImpl.h"
41 #include "TCSErrorCodes.h"
42
43
44 #define TCS_CONSTRUCT_ERRCODE(m, e) (((m) << 24) | (e))
45
46 #define PLUGIN_PATH "/opt/usr/share/sec_plugin/libengine.so"
47
48
49 typedef TCSLIB_HANDLE (*FuncLibraryOpen)(void);
50 typedef int (*FuncLibraryClose)(TCSLIB_HANDLE hLib);
51 typedef TCSErrorCode (*FuncGetLastError)(TCSLIB_HANDLE hLib);
52 typedef int (*FuncScanData)(TCSLIB_HANDLE hLib, TCSScanParam *pParam, TCSScanResult *pResult);
53 typedef int (*FuncScanFile)(TCSLIB_HANDLE hLib, char const *pszFileName, int iDataType,
54                             int iAction, int iCompressFlag, TCSScanResult *pResult);
55 typedef int (*FuncScanFileEx)(TCSLIB_HANDLE hLib, char const *pszFileName, int iDataType,
56                             int iAction, int iCompressFlag,
57                             void *pPrivate, int (*pfCallBack)(void *pPrivate, int iReason, void *pParam),
58                             TCSScanResult *pResult);
59 typedef char const* (*FuncGetVersion)();
60 typedef char const* (*FuncGetInfo)();
61
62 typedef struct PluginContext_struct
63 {
64     TCSLIB_HANDLE hLib;
65     void *pPlugin;
66     FuncLibraryOpen pfLibraryOpen;
67     FuncLibraryClose pfLibraryClose;
68     FuncGetLastError pfGetLastError;
69     FuncScanData pfScanData;
70     FuncScanFile pfScanFile;
71     FuncScanFileEx pfScanFileEx;
72     FuncGetVersion pfGetVersion;
73     FuncGetInfo pfGetInfo;
74     pthread_mutex_t mutex;
75 } PluginContext;
76
77 typedef struct ThreadScanFileData_struct
78 {
79     TCSLIB_HANDLE hLib;
80     char* pszFileName;
81     int iDataType;
82     int iAction;
83     int iCompressFlag;
84     void *pPrivate;
85     int (*pfCallBack)(void *pPrivate, int iReason, void *pParam);
86 } ThreadScanFileData;
87
88 typedef struct ThreadScanData_struct
89 {
90     TCSLIB_HANDLE hLib;
91     TCSScanParam *pParam;
92 } ThreadScanData;
93
94 static PluginContext *LoadPlugin(void);
95
96
97 TCSLIB_HANDLE TCSLibraryOpen(void)
98 {
99     PluginContext *pCtx = NULL;
100
101     DDBG("%s", "tcs lib open\n");
102     pCtx = LoadPlugin();
103     if (pCtx != NULL)
104     {
105         if (pCtx->pfLibraryOpen == NULL)
106         {
107             free(pCtx);
108             return INVALID_TCSLIB_HANDLE;
109         }
110         DDBG("%s", "call to TCSPLibraryOpen\n");
111         pCtx->hLib = (*pCtx->pfLibraryOpen)();
112         if (pCtx->hLib == INVALID_TCSLIB_HANDLE)
113         {
114             DDBG("%s", "failed to open engine\n");
115             if (pCtx->pPlugin != NULL)
116                 dlclose(pCtx->pPlugin);
117             free(pCtx);
118         }
119         else
120         {
121             pthread_mutex_init(&(pCtx->mutex), NULL);
122             return (TCSLIB_HANDLE) pCtx;
123         }
124     }
125
126     return INVALID_TCSLIB_HANDLE;
127 }
128
129
130 int TCSGetVersion(TCSLIB_HANDLE hLib, TCSVerInfo *pVerInfo)
131 {
132     PluginContext *pCtx = (PluginContext *) hLib;
133
134     if (pCtx == NULL || pCtx->pfGetVersion == NULL)
135     {
136         return -1;
137     }
138
139     if (pVerInfo == NULL)
140     {
141         return -1;
142     }
143
144     strncpy(pVerInfo->szFrameworkVer, TCS_FRAMEWORK_VERSION, TCS_VER_MAX);
145
146     char const *pPluginVer = (*pCtx->pfGetVersion)();
147
148     if (pPluginVer != NULL)
149         strncpy(pVerInfo->szPluginVer, pPluginVer, TCS_VER_MAX - 1);
150     else
151         strncpy(pVerInfo->szPluginVer, "NULL", TCS_VER_MAX - 1);
152
153     pVerInfo->szPluginVer[TCS_VER_MAX - 1] = '\0';
154
155     DDBG("%s %s %s\n", "Framework|Plugin version = ",
156               pVerInfo->szFrameworkVer, pVerInfo->szPluginVer);
157
158     return 0;
159 }
160
161 int TCSGetInfo(TCSLIB_HANDLE hLib, char *pszInfo)
162 {
163     PluginContext *pCtx = (PluginContext *) hLib;
164
165     if (pCtx == NULL || pCtx->pfGetInfo == NULL)
166     {
167         return -1;
168     }
169
170     if (pszInfo == NULL)
171     {
172         return -1;
173     }
174
175     char const *pszInfoPlugin = (*pCtx->pfGetInfo)();
176
177     if (pszInfoPlugin != NULL)
178         strncpy(pszInfo, pszInfoPlugin, TCS_META_MAX - 1);
179     else
180         strncpy(pszInfo, "NULL", TCS_META_MAX - 1);
181
182     pszInfo[TCS_META_MAX - 1] = '\0';
183
184     return 0;
185 }
186
187 int TCSLibraryClose(TCSLIB_HANDLE hLib)
188 {
189     int iRet = -1;
190     PluginContext *pCtx = NULL;
191
192     if (hLib == INVALID_TCSLIB_HANDLE)
193         return iRet;
194
195     pCtx = (PluginContext *) hLib;
196     if (pCtx->pfLibraryClose == NULL)
197         return iRet;
198
199     pthread_mutex_lock(&(pCtx->mutex));
200     iRet = (*pCtx->pfLibraryClose)(pCtx->hLib);
201
202     if (pCtx->pPlugin != NULL)
203     {
204         dlclose(pCtx->pPlugin);
205         pCtx->pPlugin = NULL;
206     }
207
208     pthread_mutex_unlock(&(pCtx->mutex));
209     pthread_mutex_destroy(&(pCtx->mutex));
210     free(pCtx);
211
212     return iRet;
213 }
214
215
216 TCSErrorCode TCSGetLastError(TCSLIB_HANDLE hLib)
217 {
218     PluginContext *pCtx = (PluginContext *) hLib;
219
220     if (pCtx == NULL || pCtx->pfGetLastError == NULL)
221     {
222         return TCS_CONSTRUCT_ERRCODE(TCS_ERROR_MODULE_GENERIC,
223                                      TCS_ERROR_NOT_IMPLEMENTED);
224     }
225
226     pthread_mutex_lock(&(pCtx->mutex));
227     TCSErrorCode errorCode = (*pCtx->pfGetLastError)(pCtx->hLib);
228     pthread_mutex_unlock(&(pCtx->mutex));
229
230     return errorCode;
231 }
232
233
234 int TCSScanData(TCSLIB_HANDLE hLib, TCSScanParam *pParam, TCSScanResult *pResult)
235 {
236     PluginContext *pCtx = (PluginContext *) hLib;
237
238     if (pCtx == NULL || pCtx->pfScanData == NULL)
239     {
240         return -1;
241     }
242     return (*pCtx->pfScanData)(pCtx->hLib, pParam, pResult);
243 }
244
245
246 int TCSScanFile(TCSLIB_HANDLE hLib, char const *pszFileName, int iDataType,
247                 int iAction, int iCompressFlag, TCSScanResult *pResult)
248 {
249     PluginContext *pCtx = (PluginContext *) hLib;
250
251     if (pCtx == NULL || pCtx->pfScanFile == NULL)
252     {
253         return -1;
254     }
255     return (*pCtx->pfScanFile)(pCtx->hLib, pszFileName, iDataType, iAction, iCompressFlag, pResult);
256 }
257
258 int TCSScanFileEx(TCSLIB_HANDLE hLib, char const *pszFileName, int iDataType,
259                 int iAction, int iCompressFlag, void *pPrivate,
260                 int (*pfCallBack)(void *pPrivate, int iReason, void *pParam),
261                 TCSScanResult *pResult)
262 {
263     PluginContext *pCtx = (PluginContext *) hLib;
264
265     if (pCtx == NULL || pCtx->pfScanFile == NULL)
266     {
267         return -1;
268     }
269     return (*pCtx->pfScanFileEx)(pCtx->hLib, pszFileName, iDataType, iAction, iCompressFlag,
270                                 pPrivate, pfCallBack, pResult);
271 }
272
273 int TCSScanAsyncCreateThread(void *pfWorkerFunc, void *pThreadData)
274 {
275     pthread_t thread;
276     pthread_attr_t attr;
277
278     int rc = -1;
279     do
280     {
281         if (pthread_attr_init(&attr) != 0)
282             break;
283
284         if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
285             break;
286
287         if (pthread_create(&thread, &attr, pfWorkerFunc, pThreadData) != 0)
288             break;
289
290         if (pthread_attr_destroy(&attr) != 0)
291             break;
292
293          rc = 0;
294      }
295      while (0);
296
297      return rc;
298 }
299
300 void *TCSScanDataAsyncWorker(void *pTData)
301 {
302     ThreadScanData *pThreadData;
303     pThreadData = (ThreadScanData *) pTData;
304
305     PluginContext *pCtx = (PluginContext *) pThreadData->hLib;
306     TCSScanParam *pTCSScanParam = pThreadData->pParam;
307
308     int iRet = -1;
309
310     do
311     {
312         if (pCtx == NULL || pCtx->pfScanFile == NULL)
313         {
314             DDBG("%s", "failed to open engine\n");
315             pTCSScanParam->pfCallBack(pTCSScanParam->pPrivate, TCS_CB_SCANFINISH, NULL);
316             break;
317         }
318
319         TCSScanResult Result;
320
321         pthread_mutex_lock(&(pCtx->mutex));
322
323         iRet = TCSScanData(pThreadData->hLib, pTCSScanParam, &Result);
324
325         pthread_mutex_unlock(&(pCtx->mutex));
326
327         if (iRet != 0)
328             pTCSScanParam->pfCallBack(pTCSScanParam->pPrivate, TCS_CB_SCANFINISH, NULL);
329         else
330             pTCSScanParam->pfCallBack(pTCSScanParam->pPrivate, TCS_CB_SCANFINISH, &Result);
331     }
332     while(0);
333
334     free(pThreadData->pParam);
335     free(pThreadData);
336     pThreadData = NULL;
337
338     return NULL;
339 }
340
341 int TCSScanDataAsync(TCSLIB_HANDLE hLib, TCSScanParam *pParam)
342 {
343     ThreadScanData *pThreadData = calloc(1, sizeof(ThreadScanData));
344
345     int rc = -1;
346
347     do
348     {
349         if (pThreadData == NULL)
350             break;
351
352         pThreadData->pParam = malloc(sizeof(TCSScanParam));
353
354         if (pThreadData->pParam == 0)
355             break;
356
357         pThreadData->hLib = hLib;
358         memcpy(pThreadData->pParam, pParam, sizeof(TCSScanParam));
359
360         if (TCSScanAsyncCreateThread(TCSScanDataAsyncWorker, (void *) pThreadData) != 0)
361             break;
362
363         rc = 0;
364     }
365     while (0);
366
367     if (rc == -1)
368     {
369         if (pThreadData != NULL)
370         {
371             free(pThreadData->pParam);
372             free(pThreadData);
373         }
374     }
375
376     return rc;
377 }
378
379 void *TCSScanFileAsyncWorker(void *pTData)
380 {
381     ThreadScanFileData *pThreadData;
382     pThreadData = (ThreadScanFileData *) pTData;
383
384     PluginContext *pCtx = (PluginContext *) pThreadData->hLib;
385
386     int iRet = -1;
387
388     do
389     {
390         if (pCtx == NULL || pCtx->pfScanFile == NULL)
391         {
392             DDBG("%s", "failed to open engine\n");
393             pThreadData->pfCallBack(pThreadData->pPrivate, TCS_CB_SCANFINISH, NULL);
394             break;
395         }
396
397         TCSScanResult Result;
398
399         pthread_mutex_lock(&(pCtx->mutex));
400
401         iRet = TCSScanFileEx(pThreadData->hLib, pThreadData->pszFileName, pThreadData->iDataType,
402                            pThreadData->iAction, pThreadData->iCompressFlag, pThreadData->pPrivate,
403                            pThreadData->pfCallBack, &Result);
404
405         pthread_mutex_unlock(&(pCtx->mutex));
406
407         if (iRet != 0)
408             pThreadData->pfCallBack(pThreadData->pPrivate, TCS_CB_SCANFINISH, NULL);
409         else
410             pThreadData->pfCallBack(pThreadData->pPrivate, TCS_CB_SCANFINISH, &Result);
411     }
412     while(0);
413
414     free(pThreadData->pszFileName);
415     free(pThreadData);
416     pThreadData = NULL;
417
418     return NULL;
419 }
420
421 int TCSScanFileAsync(TCSLIB_HANDLE hLib, char const *pszFileName, int iDataType,
422         int iAction, int iCompressFlag, void *pPrivate, 
423         int (*pfCallBack)(void *pPrivate, int iReason, void *pParam))
424 {
425     ThreadScanFileData *pThreadData = calloc(1, sizeof(ThreadScanFileData));
426
427     int rc = -1;
428
429     do
430     {
431         if (pThreadData == NULL || pszFileName == NULL)
432             break;
433
434         pThreadData->hLib = hLib;
435         pThreadData->pszFileName = strdup(pszFileName);
436         pThreadData->iDataType = iDataType;
437         pThreadData->iAction = iAction;
438         pThreadData->iCompressFlag = iCompressFlag;
439         pThreadData->pPrivate = pPrivate;
440         pThreadData->pfCallBack = pfCallBack;
441
442         if (pThreadData->pszFileName == NULL)
443             break;
444
445         if (TCSScanAsyncCreateThread(TCSScanFileAsyncWorker, pThreadData) != 0)
446             break;
447
448         rc = 0;
449     }
450     while (0);
451
452     if (rc == -1)
453     {
454         if (pThreadData != NULL)
455         {
456             free(pThreadData->pszFileName);
457             free(pThreadData);
458         }
459     }
460
461     return rc;
462 }
463
464 static PluginContext *LoadPlugin(void)
465 {
466     PluginContext *pCtx = NULL;
467     void *pTmp = dlopen(PLUGIN_PATH, RTLD_LAZY);
468     DDBG("%s", "load plugin\n");
469     if (pTmp != NULL)
470     {
471         FuncLibraryOpen TmpLibraryOpen;
472         FuncLibraryClose TmpLibraryClose;
473         FuncGetLastError TmpGetLastError;
474         FuncScanData TmpScanData;
475         FuncScanFile TmpScanFile;
476         FuncScanFileEx TmpScanFileEx;
477         FuncGetVersion TmpGetVersion;
478         FuncGetInfo TmpGetInfo;
479         
480         do
481         {
482             TmpLibraryOpen = dlsym(pTmp, "TCSPLibraryOpen");
483             DDBG("%s", "load api TCSPLibraryOpen\n");
484             if (TmpLibraryOpen == NULL)
485             {
486                 DDBG("Failed to load TCSPLibraryOpen in %s\n", PLUGIN_PATH);
487                 dlclose(pTmp);
488                 break;
489             }
490             
491             TmpLibraryClose = dlsym(pTmp, "TCSPLibraryClose");
492             if (TmpLibraryClose == NULL)
493             {
494                 DDBG("Failed to load TCSPLibraryClose in %s\n", PLUGIN_PATH);
495                 dlclose(pTmp);
496                 break;
497             }
498             
499             TmpGetLastError = dlsym(pTmp, "TCSPGetLastError");
500             if (TmpGetLastError == NULL)
501             {
502                 DDBG("Failed to load TCSPGetLastError in %s\n", PLUGIN_PATH);
503                 dlclose(pTmp);
504                 break;
505             }
506             
507             TmpScanData = dlsym(pTmp, "TCSPScanData");
508             if (TmpScanData == NULL)
509             {
510                 DDBG("Failed to load TCSPScanData in %s\n", PLUGIN_PATH);
511                 dlclose(pTmp);
512                 break;
513             }
514             
515             TmpScanFile = dlsym(pTmp, "TCSPScanFile");
516             if (TmpScanFile == NULL)
517             {
518                 DDBG("Failed to load TCSPScanFile in %s\n", PLUGIN_PATH);
519                 dlclose(pTmp);
520                 break;
521             }
522
523             TmpScanFileEx = dlsym(pTmp, "TCSPScanFileEx");
524             if (TmpScanFileEx == NULL)
525             {
526                 DDBG("Failed to load TCSPScanFileEx in %s\n", PLUGIN_PATH);
527                 dlclose(pTmp);
528                 break;
529             }
530             
531             TmpGetVersion = dlsym(pTmp, "TCSPGetVersion");
532             if(TmpGetVersion == NULL)
533             {
534                 DDBG("Failed to load TCSPGetVersion in %s\n", PLUGIN_PATH);
535                 dlclose(pTmp);
536                 break;
537             }
538
539             TmpGetInfo = dlsym(pTmp, "TCSPGetInfo");
540             if(TmpGetInfo == NULL)
541             {
542                 DDBG("Failed to load TCSPGetInfo in %s\n", PLUGIN_PATH);
543                 dlclose(pTmp);
544                 break;
545             }
546
547             pCtx = (PluginContext *) malloc(sizeof(PluginContext));
548             if (pCtx == NULL)
549             {
550                 dlclose(pTmp);
551                 break;
552             }
553             pCtx->pPlugin = pTmp;
554             pCtx->pfLibraryOpen = TmpLibraryOpen;
555             pCtx->pfLibraryClose = TmpLibraryClose;
556             pCtx->pfGetLastError = TmpGetLastError;
557             pCtx->pfScanData = TmpScanData;
558             pCtx->pfScanFile = TmpScanFile;
559             pCtx->pfScanFileEx = TmpScanFileEx;
560             pCtx->pfGetVersion = TmpGetVersion;
561             pCtx->pfGetInfo = TmpGetInfo;
562
563         } while(0);
564     }
565     else
566     {
567         DDBG("No plugin found. %s\n", dlerror());
568     }
569
570     return pCtx;
571 }
572
573