50de3b7669682e02498413db6306cbf2c471adc6
[strongswan.git] / src / libimcv / plugins / imv_os / imv_os_database.c
1 /*
2 * Copyright (C) 2012 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 #include "imv_os_database.h"
17
18 #include <utils/debug.h>
19
20 typedef struct private_imv_os_database_t private_imv_os_database_t;
21
22 /**
23 * Private data of a imv_os_database_t object.
24 *
25 */
26 struct private_imv_os_database_t {
27
28 /**
29 * Public imv_os_database_t interface.
30 */
31 imv_os_database_t public;
32
33 /**
34 * database instance
35 */
36 database_t *db;
37
38 };
39
40 METHOD(imv_os_database_t, check_packages, status_t,
41 private_imv_os_database_t *this, char *os_info,
42 enumerator_t *package_enumerator)
43 {
44 char *product, *package, *release, *cur_release, *pos;
45 size_t len;
46 int pid, gid, security, i;
47 int count = 0, count_ok = 0, count_no_match = 0, count_not_found = 0;
48 enumerator_t *e;
49 chunk_t name, version;
50 status_t status = SUCCESS;
51 bool found, match;
52
53 char *platform[] = {
54 "i686",
55 "x86_64"
56 };
57
58 /* looking for appended platform info */
59 for (i = 0; i < countof(platform); i++)
60 {
61 pos = strstr(os_info, platform[i]);
62 if (pos)
63 {
64 break;
65 }
66 }
67 if (pos)
68 {
69 /* Remove platform info, leaving OS name and version only */
70 len = pos - os_info - 1;
71 product = malloc(len + 1);
72 memcpy(product, os_info, len);
73 product[len] = '\0';
74 }
75 else
76 {
77 product = strdup(os_info);
78 }
79
80 /* Get primary key of product */
81 e = this->db->query(this->db,
82 "SELECT id FROM products WHERE name = ?",
83 DB_TEXT, product, DB_INT);
84 if (!e)
85 {
86 free(product);
87 return FAILED;
88 }
89 if (!e->enumerate(e, &pid))
90 {
91 e->destroy(e);
92 free(product);
93 return NOT_FOUND;
94 }
95 e->destroy(e);
96
97 while (package_enumerator->enumerate(package_enumerator, &name, &version))
98 {
99 /* Convert package name chunk to a string */
100 package = malloc(name.len + 1);
101 memcpy(package, name.ptr, name.len);
102 package[name.len] = '\0';
103 count++;
104
105 /* Get primary key of package */
106 e = this->db->query(this->db,
107 "SELECT id FROM packages WHERE name = ?",
108 DB_TEXT, package, DB_INT);
109 if (!e)
110 {
111 free(product);
112 free(package);
113 return FAILED;
114 }
115 if (!e->enumerate(e, &gid))
116 {
117 /* package not present in database for any product - skip */
118 count_not_found++;
119 e->destroy(e);
120 continue;
121 }
122 e->destroy(e);
123
124 /* Convert package version chunk to a string */
125 release = malloc(version.len + 1);
126 memcpy(release, version.ptr, version.len);
127 release[version.len] = '\0';
128
129 /* Enumerate over all acceptable versions */
130 e = this->db->query(this->db,
131 "SELECT release, security FROM versions "
132 "WHERE product = ? AND package = ?",
133 DB_INT, pid, DB_INT, gid, DB_TEXT, DB_INT);
134 if (!e)
135 {
136 free(product);
137 free(package);
138 free(release);
139 return FAILED;
140 }
141 found = FALSE;
142 match = FALSE;
143
144 while (e->enumerate(e, &cur_release, &security))
145 {
146 found = TRUE;
147 if (streq(release, cur_release))
148 {
149 match = TRUE;
150 break;
151 }
152 }
153 e->destroy(e);
154
155 if (found)
156 {
157 if (match)
158 {
159 DBG2(DBG_IMV, "package '%s' (%s)%s is ok", package, release,
160 security ? " [s]" : "");
161 count_ok++;
162 }
163 else
164 {
165 DBG1(DBG_IMV, "package '%s' (%s) no match", package, release);
166 count_no_match++;
167 status = VERIFY_ERROR;
168 }
169 }
170 else
171 {
172 /* package not present in database for this product - skip */
173 count_not_found++;
174 }
175 free(package);
176 free(release);
177 }
178 free(product);
179
180 DBG1(DBG_IMV, "processed %d packages: %d no match, %d ok, %d not found",
181 count, count_no_match, count_ok, count_not_found);
182
183 return status;
184 }
185
186 METHOD(imv_os_database_t, destroy, void,
187 private_imv_os_database_t *this)
188 {
189 this->db->destroy(this->db);
190 free(this);
191 }
192
193 /**
194 * See header
195 */
196 imv_os_database_t *imv_os_database_create(char *uri)
197 {
198 private_imv_os_database_t *this;
199
200 INIT(this,
201 .public = {
202 .check_packages = _check_packages,
203 .destroy = _destroy,
204 },
205 .db = lib->db->create(lib->db, uri),
206 );
207
208 if (!this->db)
209 {
210 DBG1(DBG_IMV,
211 "failed to connect to OS database '%s'", uri);
212 free(this);
213 return NULL;
214 }
215
216 return &this->public;
217 }
218