rpm  5.4.15
rpmsm.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #if defined(WITH_SEMANAGE)
8 #include <semanage/semanage.h>
9 #endif
10 
11 #define _RPMSM_INTERNAL
12 #include <rpmsm.h>
13 #include <rpmlog.h>
14 #include <rpmmacro.h>
15 #include <argv.h>
16 #include <mire.h>
17 
18 #include "debug.h"
19 
20 /*@unchecked@*/
21 int _rpmsm_debug = 0;
22 
23 /*@unchecked@*/ /*@relnull@*/
24 rpmsm _rpmsmI = NULL;
25 
26 #define F_ISSET(_sm, _FLAG) (((_sm)->flags & ((RPMSM_FLAGS_##_FLAG) & ~0x40000000)) != RPMSM_FLAGS_NONE)
27 
35 };
36 
37 /*==============================================================*/
38 #if defined(WITH_SEMANAGE)
39 static int rpmsmChk(rpmsm sm, int rc, const char * msg)
40 {
41  if (rc < 0 && msg != NULL) {
42  rpmiobAppend(sm->iob, "semanage_", 0);
43  rpmiobAppend(sm->iob, msg, 0);
44  if (errno) {
45  rpmiobAppend(sm->iob, ": ", 0);
46  rpmiobAppend(sm->iob, strerror(errno), 0);
47  }
48  }
49  return rc;
50 }
51 
52 static int rpmsmSelect(rpmsm sm, char * arg)
53 {
54  int rc = 0;
55  if (sm->state < RPMSM_STATE_SELECTED) {
56  /* Select "targeted" or other store. */
57  if (arg) {
58  semanage_select_store(sm->I, arg, SEMANAGE_CON_DIRECT);
59  sm->fn = xstrdup(arg);
60  } else
61  sm->fn = _free(sm->fn);
62  if (rc >= 0)
63  sm->state = RPMSM_STATE_SELECTED;
64 if (_rpmsm_debug)
65 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
66  }
67  return rc;
68 }
69 
70 static int rpmsmAccess(rpmsm sm, char * arg)
71 {
72  int rc = 0;
73  if (sm->state < RPMSM_STATE_ACCESSED) {
74  if ((rc = rpmsmSelect(sm, arg)) < 0)
75  return rc;
76  /* Select "targeted" or other store. */
77  rc = rpmsmChk(sm, semanage_access_check(sm->I), "access_check");
78  if (rc >= 0)
79  sm->state = RPMSM_STATE_ACCESSED;
80 if (_rpmsm_debug)
81 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
82  }
83  return rc;
84 }
85 
86 static int rpmsmCreate(rpmsm sm, char * arg)
87 {
88  int rc = 0;
89  if (sm->state < RPMSM_STATE_CREATED) {
90  if ((sm->access = rc = rpmsmAccess(sm, arg)) < SEMANAGE_CAN_READ) {
91  /* XXX error message */
92  if (rc >= 0)
93  rc = -1;
94  } else
95  semanage_set_create_store(sm->I, (F_ISSET(sm, CREATE) ? 1 : 0));
96  if (rc >= 0)
97  sm->state = RPMSM_STATE_CREATED;
98 if (_rpmsm_debug)
99 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
100  }
101  return rc;
102 }
103 
104 static int rpmsmConnect(rpmsm sm, char * arg)
105 {
106  int rc = 0;
107  if (sm->state < RPMSM_STATE_CONNECTED) {
108  if ((rc = rpmsmCreate(sm, arg)) < 0)
109  return rc;
110  if (!semanage_is_connected(sm->I))
111  rc = rpmsmChk(sm, semanage_connect(sm->I), "connect");
112  if (rc >= 0)
113  sm->state = RPMSM_STATE_CONNECTED;
114 if (_rpmsm_debug)
115 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
116  }
117  return rc;
118 }
119 #endif /* WITH_SEMANAGE */
120 
121 static int rpmsmBegin(rpmsm sm, char * arg)
122 {
123  int rc = 0;
124 #if defined(WITH_SEMANAGE)
125  if (sm->state < RPMSM_STATE_TRANSACTION) {
126  rc = rpmsmChk(sm, semanage_begin_transaction(sm->I), "begin_transaction");
127  if (rc >= 0)
128  sm->state = RPMSM_STATE_TRANSACTION;
129 if (_rpmsm_debug)
130 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
131  }
132 #endif
133  return rc;
134 }
135 
136 static int rpmsmDisconnect(rpmsm sm, char * arg)
137 {
138  int rc = 0;
139 #if defined(WITH_SEMANAGE)
140  if (sm->state >= RPMSM_STATE_CONNECTED) {
141  if (semanage_is_connected(sm->I))
142  rc = rpmsmChk(sm, semanage_disconnect(sm->I), "disconnect");
143 if (_rpmsm_debug)
144 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
145  /* XXX check rc? */
146  sm->state = RPMSM_STATE_CLOSED;
147  }
148 #endif
149  return rc;
150 }
151 
152 static int rpmsmReload(rpmsm sm, char * arg)
153 {
154  int rc = 0;
155 #if defined(WITH_SEMANAGE)
156  /* Make sure policy store can be accessed. */
157  if ((rc = rpmsmConnect(sm, sm->fn)) < 0)
158  return rc;
159 
160 if (_rpmsm_debug)
161 fprintf(stderr, "--> %s(%p,%s) I %p\n", __FUNCTION__, sm, arg, sm->I);
162  rc = rpmsmChk(sm, semanage_reload_policy(sm->I), "reload_policy");
163 if (_rpmsm_debug)
164 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
165 #endif
166  return rc;
167 }
168 
169 static int rpmsmInstallBase(rpmsm sm, char * arg)
170 {
171  int rc = 0;
172 #if defined(WITH_SEMANAGE)
173  /* Make sure policy store can be accessed. */
174  if ((rc = rpmsmConnect(sm, sm->fn)) < 0)
175  return rc;
176 
177  rc = rpmsmChk(sm, semanage_module_install_base_file(sm->I, arg), "module_install_base_file");
178  if (rc >= 0)
179  sm->flags |= RPMSM_FLAGS_COMMIT;
180 if (_rpmsm_debug)
181 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
182 #endif
183  return rc;
184 }
185 
186 static int rpmsmInstall(rpmsm sm, char * arg)
187 {
188  int rc = 0;
189 #if defined(WITH_SEMANAGE)
190  /* Make sure policy store can be accessed. */
191  if ((rc = rpmsmConnect(sm, sm->fn)) < 0)
192  return rc;
193 
194 if (_rpmsm_debug)
195 fprintf(stderr, "--> %s(%p,%s) I %p\n", __FUNCTION__, sm, arg, sm->I);
196  rc = rpmsmChk(sm, semanage_module_install_file(sm->I, arg), "module_install_file");
197  if (rc >= 0)
198  sm->flags |= RPMSM_FLAGS_COMMIT;
199 if (_rpmsm_debug)
200 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
201 #endif
202  return rc;
203 }
204 
205 static int rpmsmUpgrade(rpmsm sm, char * arg)
206 {
207  int rc = 0;
208 #if defined(WITH_SEMANAGE)
209  /* Make sure policy store can be accessed. */
210  if ((rc = rpmsmConnect(sm, sm->fn)) < 0)
211  return rc;
212 
213 if (_rpmsm_debug)
214 fprintf(stderr, "--> %s(%p,%s) I %p\n", __FUNCTION__, sm, arg, sm->I);
215  rc = rpmsmChk(sm, semanage_module_upgrade_file(sm->I, arg), "module_upgrade_file");
216  if (rc >= 0)
217  sm->flags |= RPMSM_FLAGS_COMMIT;
218 if (_rpmsm_debug)
219 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
220 #endif
221  return rc;
222 }
223 
224 static int rpmsmRemove(rpmsm sm, char * arg)
225 {
226  int rc = 0;
227 #if defined(WITH_SEMANAGE)
228  /* Make sure policy store can be accessed. */
229  if ((rc = rpmsmConnect(sm, sm->fn)) < 0)
230  return rc;
231 
232  rc = rpmsmChk(sm, semanage_module_remove(sm->I, arg), "module_remove");
233  if (rc >= 0)
234  sm->flags |= RPMSM_FLAGS_COMMIT;
235 if (_rpmsm_debug)
236 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
237 #endif
238  return rc;
239 }
240 
241 static int rpmsmList(rpmsm sm, char * arg)
242 {
243  int rc = 0;
244 #if defined(WITH_SEMANAGE)
245  semanage_module_info_t *modules = NULL;
246  int nmodules = 0;
247 
248  /* Make sure policy store can be accessed. */
249  if ((rc = rpmsmConnect(sm, sm->fn)) < 0)
250  return rc;
251 
252  rc = rpmsmChk(sm, semanage_module_list(sm->I, &modules, &nmodules), "module_list");
253  if (rc >= 0) {
254  miRE include = NULL;
255  int ninclude = 0;
256  int j;
257 
258  if (arg && *arg) {
259  include = mireNew(RPMMIRE_REGEX, 0);
260  (void) mireRegcomp(include, arg);
261  ninclude++;
262  }
263 
264  for (j = 0; j < nmodules; j++) {
265  semanage_module_info_t * m = semanage_module_list_nth(modules, j);
266  char * NV = rpmExpand(semanage_module_get_name(m), "-",
267  semanage_module_get_version(m), NULL);
268  if (include == NULL
269  || !(mireApply(include, ninclude, NV, 0, +1) < 0))
270  rpmiobAppend(sm->iob, NV, 1);
271  NV = _free(NV);
272  semanage_module_info_datum_destroy(m);
273  }
274 
275  include = mireFree(include);
276  modules = _free(modules);
277  }
278 if (_rpmsm_debug)
279 fprintf(stderr, "<-- %s(%p,%s) I %p rc %d\n", __FUNCTION__, sm, arg, sm->I, rc);
280 #endif
281  return rc;
282 }
283 
284 static int rpmsmCommit(rpmsm sm, char * arg)
285 {
286  int rc = 0;
287 #if defined(WITH_SEMANAGE)
288  if (F_ISSET(sm, COMMIT)) {
289  semanage_set_reload(sm->I, (F_ISSET(sm, RELOAD) ? 1 : 0));
290  semanage_set_rebuild(sm->I, (F_ISSET(sm, REBUILD) ? 1 : 0));
291  semanage_set_disable_dontaudit(sm->I, (F_ISSET(sm, NOAUDIT) ? 1 : 0));
292  rc = rpmsmChk(sm, semanage_commit(sm->I), "commit");
293  /* XXX check rc? */
294  sm->flags &= ~RPMSM_FLAGS_COMMIT;
295  }
296 if (_rpmsm_debug)
297 fprintf(stderr, "<-- %s(%p) I %p rc %d\n", __FUNCTION__, sm, sm->I, rc);
298 #endif
299  return rc;
300 }
301 
302 /*==============================================================*/
303 
304 static void rpmsmFini(void * _sm)
305  /*@globals fileSystem @*/
306  /*@modifies *_sm, fileSystem @*/
307 {
308  rpmsm sm = (rpmsm) _sm;
309 
310 #if defined(WITH_SEMANAGE)
311  if (sm->I) {
312  rpmsmDisconnect(sm, NULL);
313  semanage_handle_destroy(sm->I);
314  }
315 #endif
316  (void) rpmiobFree(sm->iob);
317  sm->iob = NULL;
318  sm->fn = _free(sm->fn);
319  sm->flags = 0;
320  sm->state = RPMSM_STATE_CLOSED;
321  sm->access = 0;
322  sm->av = argvFree(sm->av);
323  sm->I = NULL;
324 }
325 
326 /*@unchecked@*/ /*@only@*/ /*@null@*/
328 
329 static rpmsm rpmsmGetPool(/*@null@*/ rpmioPool pool)
330  /*@globals _rpmsmPool, fileSystem @*/
331  /*@modifies pool, _rpmsmPool, fileSystem @*/
332 {
333  rpmsm sm;
334 
335  if (_rpmsmPool == NULL) {
336  _rpmsmPool = rpmioNewPool("sm", sizeof(*sm), -1, _rpmsm_debug,
337  NULL, NULL, rpmsmFini);
338  pool = _rpmsmPool;
339  }
340  return (rpmsm) rpmioGetPool(pool, sizeof(*sm));
341 }
342 
343 rpmsm rpmsmNew(const char * fn, unsigned int flags)
344 {
345  rpmsm sm = rpmsmGetPool(_rpmsmPool);
346 
347  sm->fn = NULL;
348  sm->flags = 0;
349  sm->state = 0;
350  sm->access = 0;
351  sm->av = NULL;
352  sm->I = NULL;
353  sm->iob = rpmiobNew(0);
354 
355 #if defined(WITH_SEMANAGE)
356  { int rc;
357 
358  /* Connect to the policy store immediately in known (if requested). */
359  if ((sm->I = semanage_handle_create()) == NULL)
360  rc = -1;
361  else if (flags & RPMSM_FLAGS_BEGIN)
362  rc = rpmsmBegin(sm, (char *)fn);
363  else if (flags & RPMSM_FLAGS_CONNECT)
364  rc = rpmsmConnect(sm, (char *)fn);
365  else if (flags & RPMSM_FLAGS_CREATE)
366  rc = rpmsmCreate(sm, (char *)fn);
367  else if (flags & RPMSM_FLAGS_ACCESS)
368  rc = rpmsmAccess(sm, (char *)fn);
369  else if (flags & RPMSM_FLAGS_SELECT)
370  rc = rpmsmSelect(sm, (char *)fn);
371  else
372  rc = 0;
373 
374  if (rc < 0) {
375  (void)rpmsmFree(sm);
376  return NULL;
377  }
378  }
379 #endif
380 
381  return rpmsmLink(sm);
382 }
383 
384 /*@unchecked@*/ /*@null@*/
385 static const char _rpmsmI_fn[] = "minimum";
386 /*@unchecked@*/
387 static int _rpmsmI_flags;
388 
389 static rpmsm rpmsmI(void)
390  /*@globals _rpmsmI @*/
391  /*@modifies _rpmsmI @*/
392 {
393  if (_rpmsmI == NULL)
394  _rpmsmI = rpmsmNew(_rpmsmI_fn, _rpmsmI_flags);
395  return _rpmsmI;
396 }
397 
398 /*==============================================================*/
399 
400 rpmRC rpmsmRun(rpmsm sm, char ** av, const char ** resultp)
401 {
402  int ncmds = argvCount((ARGV_t)av);
403  int rc = 0;
404  int i;
405 
406 if (_rpmsm_debug)
407 fprintf(stderr, "--> %s(%p,%p,%p) av[0] \"%s\"\n", __FUNCTION__, sm, av, resultp, (av ? av[0] : NULL));
408 
409  if (sm == NULL) sm = rpmsmI();
410 
411  (void) rpmiobEmpty(sm->iob);
412 
413  for (i = 0; i < ncmds; i++) {
414  char * cmd = (char *)av[i];
415  char * arg = strchr(cmd+1, ' ');
416 
417  if (arg)
418  while (xisspace(*arg)) arg++;
419 
420  switch (*cmd) {
421  case 'l':
422  rc = rpmsmList(sm, arg);
423  break;
424  case 'b':
425  rc = rpmsmInstallBase(sm, arg);
426  break;
427  case 'i':
428  rc = rpmsmInstall(sm, arg);
429  break;
430  case 'u':
431  rc = rpmsmUpgrade(sm, arg);
432  break;
433  case 'r':
434  rc = rpmsmRemove(sm, arg);
435  if (rc == -2) { /* XXX WTF? */
436  rc = 0;
437  continue;
438  }
439  break;
440  case 'R':
441  rc = rpmsmReload(sm, arg);
442  break;
443  case 'B':
444  rc = rpmsmBegin(sm, arg);
445  sm->flags |= RPMSM_FLAGS_COMMIT; /* XXX from semanage CLI */
446  sm->flags &= ~RPMSM_FLAGS_NOAUDIT; /* XXX for rpmsmCommit() */
447  break;
448  default:
449  rpmiobAppend(sm->iob, "Unknown cmd: \"", 0);
450  rpmiobAppend(sm->iob, cmd, 0);
451  rpmiobAppend(sm->iob, "\"", 0);
452  goto exit;
453  /*@notreached@*/ break;
454  }
455  }
456 
457 exit:
458  /* Commit any pending transactions. */
459  if (!rc && F_ISSET(sm, COMMIT))
460  rc = rpmsmCommit(sm, sm->fn);
461 
462  /* Disconnect from policy store (if connected). */
463  if (F_ISSET(sm, CONNECT)) {
464  int xx = rpmsmDisconnect(sm, sm->fn);
465  if (xx && !rc)
466  rc = xx;
467  }
468 
469  /* Return any/all spewage to caller. */
470  (void) rpmiobRTrim(sm->iob);
471  if (resultp) /* XXX xstrdup? */
472  *resultp = (rpmiobLen(sm->iob) > 0 ? rpmiobStr(sm->iob) : NULL);
473 
474 if (_rpmsm_debug)
475 fprintf(stderr, "<-- %s(%p,%p,%p) av[0] \"%s\" rc %d\n", __FUNCTION__, sm, av, resultp, (av ? av[0] : NULL), rc);
476  /* XXX impedance match to OK or FAIL return codes. */
477  return (rc >= 0 ? RPMRC_OK : RPMRC_FAIL);
478 }
rpmiob rpmiobRTrim(rpmiob iob)
Trim trailing white space.
Definition: rpmiob.c:67
static const char _rpmsmI_fn[]
Definition: rpmsm.c:385
rpmsm rpmsmFree(rpmsm sm)
Destroy a semanage wrapper.
miRE mireNew(rpmMireMode mode, int tag)
Create pattern container.
Definition: mire.c:113
int mireApply(miRE mire, int nmire, const char *s, size_t slen, int rc)
Apply array of patterns to a string.
Definition: mire.c:551
rpmsm rpmsmLink(rpmsm sm)
Reference a semanage wrapper instance.
const char const char * cmd
Definition: mongo.h:777
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
size_t rpmiobLen(rpmiob iob)
Return I/O buffer len.
Definition: rpmiob.c:122
int _rpmsm_debug
Definition: rpmsm.c:21
static int rpmsmList(rpmsm sm, char *arg)
Definition: rpmsm.c:241
int mireRegcomp(miRE mire, const char *pattern)
Compile pattern match.
Definition: mire.c:332
static int rpmsmInstallBase(rpmsm sm, char *arg)
Definition: rpmsm.c:169
static int rpmsmReload(rpmsm sm, char *arg)
Definition: rpmsm.c:152
struct rpmsm_s * rpmsm
Definition: rpmsm.h:11
int errno
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:77
Yet Another syslog(3) API clone.
static rpmsm rpmsmI(void)
Definition: rpmsm.c:389
miRE mireFree(miRE mire)
Free pattern container.
static int rpmsmDisconnect(rpmsm sm, char *arg)
Definition: rpmsm.c:136
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
RPM pattern matching.
int argvCount(const ARGV_t argv)
Return no.
Definition: argv.c:71
static int rpmsmCommit(rpmsm sm, char *arg)
Definition: rpmsm.c:284
static int xisspace(int c)
Definition: rpmiotypes.h:555
rpmsmState_e
Definition: rpmsm.c:28
static int rpmsmInstall(rpmsm sm, char *arg)
Definition: rpmsm.c:186
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
struct miRE_s * miRE
Definition: mire.h:60
rpmRC rpmsmRun(rpmsm sm, char **av, const char **resultp)
Run semanage commands.
Definition: rpmsm.c:400
static int rpmsmBegin(rpmsm sm, char *arg)
Definition: rpmsm.c:121
static int _rpmsmI_flags
Definition: rpmsm.c:387
#define F_ISSET(_sm, _FLAG)
Definition: rpmsm.c:26
rpmioPool _rpmsmPool
Definition: rpmsm.c:327
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3238
const char const char int arg
Definition: mongo.h:777
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
rpmsm rpmsmNew(const char *fn, unsigned int flags)
Create and load a semanage wrapper.
Definition: rpmsm.c:343
enum rpmRC_e rpmRC
RPM return codes.
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:112
const char const int i
Definition: bson.h:778
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
static int rpmsmUpgrade(rpmsm sm, char *arg)
Definition: rpmsm.c:205
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
static void rpmsmFini(void *_sm)
Definition: rpmsm.c:304
rpmiob rpmiobEmpty(rpmiob iob)
Empty an I/O buffer.
Definition: rpmiob.c:57
static int rpmsmRemove(rpmsm sm, char *arg)
Definition: rpmsm.c:224
static rpmsm rpmsmGetPool(rpmioPool pool)
Definition: rpmsm.c:329
ARGstr_t * ARGV_t
Definition: argv.h:12
rpmsm _rpmsmI
Definition: rpmsm.c:24
int j
Definition: mongo.h:438