testing: Build wolfSSL from the Git repository
[strongswan.git] / src / libimcv / plugins / imv_os / imv_os_database.c
1 /*
2 * Copyright (C) 2012-2017 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #define _GNU_SOURCE /* for stdndup() */
17 #include <string.h>
18
19 #include "imv_os_database.h"
20
21 #include <utils/debug.h>
22
23 typedef struct private_imv_os_database_t private_imv_os_database_t;
24
25 /**
26 * Private data of a imv_os_database_t object.
27 *
28 */
29 struct private_imv_os_database_t {
30
31 /**
32 * Public imv_os_database_t interface.
33 */
34 imv_os_database_t public;
35
36 /**
37 * database instance
38 */
39 database_t *db;
40
41 };
42
43 METHOD(imv_os_database_t, check_packages, status_t,
44 private_imv_os_database_t *this, imv_os_state_t *os_state,
45 enumerator_t *package_enumerator)
46 {
47 imv_state_t *state;
48 imv_session_t *session;
49 imv_os_info_t *os_info;
50 os_type_t os_type;
51 char *product, *package, *release, *cur_release;
52 chunk_t name, version;
53 int pid, gid, security, blacklist;
54 int count = 0, count_ok = 0, count_security = 0, count_blacklist = 0;
55 enumerator_t *e;
56 status_t status = SUCCESS;
57 bool found, match;
58
59 state = &os_state->interface;
60 session = state->get_session(state);
61 session->get_session_id(session, &pid, NULL);
62 os_info = session->get_os_info(session);
63 os_type = os_info->get_type(os_info);
64 product = os_info->get_info(os_info);
65
66 if (os_type == OS_TYPE_ANDROID)
67 {
68 /*no package dependency on Android version */
69 product = enum_to_name(os_type_names, os_type);
70
71 /* Get primary key of product */
72 e = this->db->query(this->db,
73 "SELECT id FROM products WHERE name = ?",
74 DB_TEXT, product, DB_INT);
75 if (!e)
76 {
77 return FAILED;
78 }
79 if (!e->enumerate(e, &pid))
80 {
81 e->destroy(e);
82 return NOT_FOUND;
83 }
84 e->destroy(e);
85 }
86 DBG1(DBG_IMV, "processing installed '%s' packages", product);
87
88 while (package_enumerator->enumerate(package_enumerator, &name, &version))
89 {
90 /* Convert package name chunk to a string */
91 package = strndup(name.ptr, name.len);
92 count++;
93
94 /* Get primary key of package */
95 e = this->db->query(this->db,
96 "SELECT id FROM packages WHERE name = ?",
97 DB_TEXT, package, DB_INT);
98 if (!e)
99 {
100 free(package);
101 return FAILED;
102 }
103 if (!e->enumerate(e, &gid))
104 {
105 /* package not present in database for any product - skip */
106 DBG2(DBG_IMV, "package '%s' (%.*s) not found",
107 package, version.len, version.ptr);
108 free(package);
109 e->destroy(e);
110 continue;
111 }
112 e->destroy(e);
113
114 /* Convert package version chunk to a string */
115 release = strndup(version.ptr, version.len);
116
117 /* Enumerate over all acceptable versions */
118 e = this->db->query(this->db,
119 "SELECT release, security, blacklist FROM versions "
120 "WHERE product = ? AND package = ?",
121 DB_INT, pid, DB_INT, gid, DB_TEXT, DB_INT, DB_INT);
122 if (!e)
123 {
124 free(package);
125 free(release);
126 return FAILED;
127 }
128 found = FALSE;
129 match = FALSE;
130
131 while (e->enumerate(e, &cur_release, &security, &blacklist))
132 {
133 found = TRUE;
134 if (streq(release, cur_release) || streq("*", cur_release))
135 {
136 match = TRUE;
137 break;
138 }
139 }
140 e->destroy(e);
141
142 if (found)
143 {
144 if (match)
145 {
146 if (blacklist)
147 {
148 DBG1(DBG_IMV, "package '%s' (%s) is blacklisted",
149 package, release);
150 count_blacklist++;
151 os_state->add_bad_package(os_state, package,
152 OS_PACKAGE_STATE_BLACKLIST);
153 }
154 else if (security)
155 {
156 DBG1(DBG_IMV, "package '%s' (%s) is vulnerable",
157 package, release);
158 os_state->add_bad_package(os_state, package,
159 OS_PACKAGE_STATE_SECURITY);
160 count_security++;
161 }
162 else
163 {
164 DBG2(DBG_IMV, "package '%s' (%s) is ok",
165 package, release);
166 count_ok++;
167 }
168 }
169 else
170 {
171 DBG1(DBG_IMV, "package '%s' (%s) no match", package, release);
172 }
173 }
174 else
175 {
176 DBG2(DBG_IMV, "package '%s' (%s) unknown", package, release);
177 }
178 free(package);
179 free(release);
180 }
181 os_state->set_count(os_state, count, count_security, count_blacklist,
182 count_ok);
183
184 return status;
185 }
186
187 METHOD(imv_os_database_t, destroy, void,
188 private_imv_os_database_t *this)
189 {
190 free(this);
191 }
192
193 /**
194 * See header
195 */
196 imv_os_database_t *imv_os_database_create(imv_database_t *imv_db)
197 {
198 private_imv_os_database_t *this;
199
200 if (!imv_db)
201 {
202 return NULL;
203 }
204
205 INIT(this,
206 .public = {
207 .check_packages = _check_packages,
208 .destroy = _destroy,
209 },
210 .db = imv_db->get_database(imv_db),
211 );
212
213 return &this->public;
214 }
215