31b889b74fac2b3decb63d6580597a5f0d952c55
[strongswan.git] / src / libimcv / plugins / imv_os / imv_os_database.c
1 /*
2 * Copyright (C) 2012-2014 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_no_match = 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 if (os_type == OS_TYPE_ANDROID)
107 {
108 DBG2(DBG_IMV, "package '%s' (%.*s) not found",
109 package, version.len, version.ptr);
110 }
111 free(package);
112 e->destroy(e);
113 continue;
114 }
115 e->destroy(e);
116
117 /* Convert package version chunk to a string */
118 release = strndup(version.ptr, version.len);
119
120 /* Enumerate over all acceptable versions */
121 e = this->db->query(this->db,
122 "SELECT release, security, blacklist FROM versions "
123 "WHERE product = ? AND package = ?",
124 DB_INT, pid, DB_INT, gid, DB_TEXT, DB_INT, DB_INT);
125 if (!e)
126 {
127 free(package);
128 free(release);
129 return FAILED;
130 }
131 found = FALSE;
132 match = FALSE;
133
134 while (e->enumerate(e, &cur_release, &security, &blacklist))
135 {
136 found = TRUE;
137 if (streq(release, cur_release) || streq("*", cur_release))
138 {
139 match = TRUE;
140 break;
141 }
142 }
143 e->destroy(e);
144
145 if (found)
146 {
147 if (match)
148 {
149 if (blacklist)
150 {
151 DBG2(DBG_IMV, "package '%s' (%s) is blacklisted",
152 package, release);
153 count_blacklist++;
154 os_state->add_bad_package(os_state, package,
155 OS_PACKAGE_STATE_BLACKLIST);
156 }
157 else
158 {
159 DBG2(DBG_IMV, "package '%s' (%s)%s is ok", package, release,
160 security ? " [s]" : "");
161 count_ok++;
162 }
163 }
164 else
165 {
166 DBG1(DBG_IMV, "package '%s' (%s) no match", package, release);
167 count_no_match++;
168 os_state->add_bad_package(os_state, package,
169 OS_PACKAGE_STATE_SECURITY);
170 }
171 }
172 else
173 {
174 /* package not present in database for this product - skip */
175 }
176 free(package);
177 free(release);
178 }
179 os_state->set_count(os_state, count, count_no_match,
180 count_blacklist, count_ok);
181
182 return status;
183 }
184
185 METHOD(imv_os_database_t, destroy, void,
186 private_imv_os_database_t *this)
187 {
188 free(this);
189 }
190
191 /**
192 * See header
193 */
194 imv_os_database_t *imv_os_database_create(imv_database_t *imv_db)
195 {
196 private_imv_os_database_t *this;
197
198 if (!imv_db)
199 {
200 return NULL;
201 }
202
203 INIT(this,
204 .public = {
205 .check_packages = _check_packages,
206 .destroy = _destroy,
207 },
208 .db = imv_db->get_database(imv_db),
209 );
210
211 return &this->public;
212 }
213