]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libimcv/swid_gen/swid_gen.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libimcv / swid_gen / swid_gen.c
1 /*
2 * Copyright (C) 2017 Andreas Steffen
3 *
4 * Copyright (C) secunet Security Networks AG
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #define _GNU_SOURCE
18 #include <stdio.h>
19
20 #include "swid_gen.h"
21
22 #include <bio/bio_writer.h>
23
24 #define SWID_GENERATOR "/usr/local/bin/swid_generator"
25
26 typedef struct private_swid_gen_t private_swid_gen_t;
27
28 /**
29 * Private data of a swid_gen_t object.
30 *
31 */
32 struct private_swid_gen_t {
33
34 /**
35 * Public swid_gen_t interface.
36 */
37 swid_gen_t public;
38
39 /**
40 * Path of the SWID generator command
41 */
42 char *generator;
43
44 /**
45 * Entity name of the tagCreator
46 */
47 char *entity;
48
49 /**
50 * Regid of the tagCreator
51 */
52 char *regid;
53
54 };
55
56 METHOD(swid_gen_t, generate_tag, char*,
57 private_swid_gen_t *this, char *sw_id, char *package, char *version,
58 bool full, bool pretty)
59 {
60 char *tag = NULL;
61 size_t tag_buf_len = 8192;
62 char tag_buf[tag_buf_len], command[BUF_LEN];
63 bio_writer_t *writer;
64 chunk_t swid_tag;
65 FILE *file;
66
67 /* Compose the SWID generator command */
68 if (full || !package || !version)
69 {
70 snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" "
71 "--regid %s --software-id %s%s%s",
72 this->generator, this->entity, this->regid, sw_id,
73 full ? " --full" : "", pretty ? " --pretty" : "");
74 }
75 else
76 {
77 snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" "
78 "--regid %s --name %s --version-string %s%s",
79 this->generator, this->entity, this->regid, package,
80 version, pretty ? " --pretty" : "");
81 }
82
83 /* Open a pipe stream for reading the SWID generator output */
84 file = popen(command, "r");
85 if (file)
86 {
87 writer = bio_writer_create(tag_buf_len);
88 while (TRUE)
89 {
90 if (!fgets(tag_buf, tag_buf_len, file))
91 {
92 break;
93 }
94 writer->write_data(writer, chunk_create(tag_buf, strlen(tag_buf)));
95 }
96 pclose(file);
97 swid_tag = writer->extract_buf(writer);
98 writer->destroy(writer);
99
100 if (swid_tag.len > 0)
101 {
102 tag = swid_tag.ptr;
103 tag[swid_tag.len - 1] = '\0';
104 }
105 else
106 {
107 chunk_free(&swid_tag);
108 }
109 }
110 else
111 {
112 DBG1(DBG_IMC, "failed to run swid_generator command");
113 }
114
115 return tag;
116 }
117
118 typedef struct {
119 /** public enumerator interface */
120 enumerator_t public;
121 /** swid_generator output stream */
122 FILE *file;
123 /** generate software identifier only */
124 bool sw_id_only;
125 } swid_gen_enumerator_t;
126
127 METHOD(enumerator_t, enumerate, bool,
128 swid_gen_enumerator_t *this, va_list args)
129 {
130 chunk_t *out;
131
132 VA_ARGS_VGET(args, out);
133
134 if (this->sw_id_only)
135 {
136 char line[BUF_LEN];
137 size_t len;
138
139 if (!fgets(line, sizeof(line), this->file))
140 {
141 return FALSE;
142 }
143 len = strlen(line);
144
145 if (len == 0)
146 {
147 return FALSE;
148 }
149
150 /* remove trailing newline if present */
151 if (line[len - 1] == '\n')
152 {
153 len--;
154 }
155 DBG3(DBG_IMC, " %.*s", len, line);
156 *out = chunk_clone(chunk_create(line, len));
157 }
158 else
159 {
160 bool last_newline = TRUE;
161 size_t len, line_len = 8192;
162 char line[line_len];
163 bio_writer_t *writer;
164 chunk_t swid_tag;
165
166 writer = bio_writer_create(line_len);
167 while (TRUE)
168 {
169 if (!fgets(line, line_len, this->file))
170 {
171 break;
172 }
173 len = strlen(line);
174
175 if (last_newline && line[0] == '\n')
176 {
177 break;
178 }
179 else
180 {
181 last_newline = (line[len-1] == '\n');
182 writer->write_data(writer, chunk_create(line, len));
183 }
184 }
185 swid_tag = writer->extract_buf(writer);
186 writer->destroy(writer);
187
188 if (swid_tag.len <= 1)
189 {
190 chunk_free(&swid_tag);
191 return FALSE;
192 }
193
194 /* remove trailing newline if present */
195 if (swid_tag.ptr[swid_tag.len - 1] == '\n')
196 {
197 swid_tag.len--;
198 }
199 DBG3(DBG_IMC, " %.*s", swid_tag.len, swid_tag.ptr);
200 *out = swid_tag;
201 }
202
203 return TRUE;
204 }
205
206 METHOD(enumerator_t, enumerator_destroy, void,
207 swid_gen_enumerator_t *this)
208 {
209 pclose(this->file);
210 free(this);
211 }
212
213 METHOD(swid_gen_t, create_tag_enumerator, enumerator_t*,
214 private_swid_gen_t *this, bool sw_id_only, bool full, bool pretty)
215 {
216 swid_gen_enumerator_t *enumerator;
217 char command[BUF_LEN];
218 char doc_separator[] = "'\n\n'";
219 FILE *file;
220
221 /* Assemble the SWID generator command */
222 if (sw_id_only)
223 {
224 snprintf(command, BUF_LEN, "%s software-id --regid %s ",
225 this->generator, this->regid);
226 }
227 else
228 {
229 snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" --regid %s "
230 "--doc-separator %s%s%s", this->generator, this->entity,
231 this->regid, doc_separator, pretty ? " --pretty" : "",
232 full ? " --full" : "");
233 }
234
235 /* Open a pipe stream for reading the SWID generator output */
236 file = popen(command, "r");
237 if (!file)
238 {
239 DBG1(DBG_IMC, "failed to run swid_generator command");
240 return NULL;
241 }
242
243 INIT(enumerator,
244 .public = {
245 .enumerate = enumerator_enumerate_default,
246 .venumerate = _enumerate,
247 .destroy = _enumerator_destroy,
248 },
249 .sw_id_only = sw_id_only,
250 .file = file,
251 );
252
253 return &enumerator->public;
254 }
255
256 METHOD(swid_gen_t, destroy, void,
257 private_swid_gen_t *this)
258 {
259 free(this->generator);
260 free(this->entity);
261 free(this->regid);
262 free(this);
263 }
264
265 /**
266 * See header
267 */
268 swid_gen_t *swid_gen_create(void)
269 {
270 private_swid_gen_t *this;
271 char *entity, *regid, *generator;
272
273 entity = lib->settings->get_str(lib->settings,
274 "libimcv.swid_gen.tag_creator.name", "strongSwan Project");
275 regid = lib->settings->get_str(lib->settings,
276 "libimcv.swid_gen.tag_creator.regid", "strongswan.org");
277 generator = lib->settings->get_str(lib->settings,
278 "libimcv.swid_gen.command", SWID_GENERATOR);
279
280 INIT(this,
281 .public = {
282 .generate_tag = _generate_tag,
283 .create_tag_enumerator = _create_tag_enumerator,
284 .destroy = _destroy,
285 },
286 .generator = strdup(generator),
287 .entity = strdup(entity),
288 .regid = strdup(regid),
289 );
290
291 return &this->public;
292 }