privs.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. /*
  2. * Zebra privileges.
  3. *
  4. * Copyright (C) 2003 Paul Jakma.
  5. * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  6. *
  7. * This file is part of GNU Zebra.
  8. *
  9. * GNU Zebra is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by the
  11. * Free Software Foundation; either version 2, or (at your option) any
  12. * later version.
  13. *
  14. * GNU Zebra is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with GNU Zebra; see the file COPYING. If not, write to the Free
  21. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  22. * 02111-1307, USA.
  23. */
  24. #include <zebra.h>
  25. #include "log.h"
  26. #include "privs.h"
  27. #include "memory.h"
  28. #ifdef HAVE_CAPABILITIES
  29. /* sort out some generic internal types for:
  30. *
  31. * privilege values (cap_value_t, priv_t) -> pvalue_t
  32. * privilege set (..., priv_set_t) -> pset_t
  33. * privilege working storage (cap_t, ...) -> pstorage_t
  34. *
  35. * values we think of as numeric (they're ints really, but we dont know)
  36. * sets are mostly opaque, to hold a set of privileges, related in some way.
  37. * storage binds together a set of sets we're interested in.
  38. * (in reality: cap_value_t and priv_t are ints)
  39. */
  40. #ifdef HAVE_LCAPS
  41. /* Linux doesn't have a 'set' type: a set of related privileges */
  42. struct _pset {
  43. int num;
  44. cap_value_t *caps;
  45. };
  46. typedef cap_value_t pvalue_t;
  47. typedef struct _pset pset_t;
  48. typedef cap_t pstorage_t;
  49. #elif defined (HAVE_SOLARIS_CAPABILITIES)
  50. typedef priv_t pvalue_t;
  51. typedef priv_set_t pset_t;
  52. typedef priv_set_t *pstorage_t;
  53. #else /* neither LCAPS nor SOLARIS_CAPABILITIES */
  54. #error "HAVE_CAPABILITIES defined, but neither LCAPS nor Solaris Capabilties!"
  55. #endif /* HAVE_LCAPS */
  56. #endif /* HAVE_CAPABILITIES */
  57. /* the default NULL state we report is RAISED, but could be LOWERED if
  58. * zprivs_terminate is called and the NULL handler is installed.
  59. */
  60. static zebra_privs_current_t zprivs_null_state = ZPRIVS_RAISED;
  61. /* internal privileges state */
  62. static struct _zprivs_t
  63. {
  64. #ifdef HAVE_CAPABILITIES
  65. pstorage_t caps; /* working storage */
  66. pset_t *syscaps_p; /* system-type requested permitted caps */
  67. pset_t *syscaps_i; /* system-type requested inheritable caps */
  68. #endif /* HAVE_CAPABILITIES */
  69. uid_t zuid, /* uid to run as */
  70. zsuid; /* saved uid */
  71. gid_t zgid; /* gid to run as */
  72. gid_t vtygrp; /* gid for vty sockets */
  73. } zprivs_state;
  74. /* externally exported but not directly accessed functions */
  75. #ifdef HAVE_CAPABILITIES
  76. int zprivs_change_caps (zebra_privs_ops_t);
  77. zebra_privs_current_t zprivs_state_caps (void);
  78. #endif /* HAVE_CAPABILITIES */
  79. int zprivs_change_uid (zebra_privs_ops_t);
  80. zebra_privs_current_t zprivs_state_uid (void);
  81. int zprivs_change_null (zebra_privs_ops_t);
  82. zebra_privs_current_t zprivs_state_null (void);
  83. #ifdef HAVE_CAPABILITIES
  84. /* internal capability API */
  85. static pset_t *zcaps2sys (zebra_capabilities_t *, int);
  86. static void zprivs_caps_init (struct zebra_privs_t *);
  87. static void zprivs_caps_terminate (void);
  88. /* Map of Quagga abstract capabilities to system capabilities */
  89. static struct
  90. {
  91. int num;
  92. pvalue_t *system_caps;
  93. } cap_map [ZCAP_MAX] =
  94. {
  95. #ifdef HAVE_LCAPS /* Quagga -> Linux capabilities mappings */
  96. [ZCAP_SETID] = { 2, (pvalue_t []) { CAP_SETGID,
  97. CAP_SETUID }, },
  98. [ZCAP_BIND] = { 1, (pvalue_t []) { CAP_NET_BIND_SERVICE }, },
  99. [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { CAP_NET_ADMIN }, },
  100. [ZCAP_NET_RAW] = { 1, (pvalue_t []) { CAP_NET_RAW }, },
  101. [ZCAP_CHROOT] = { 1, (pvalue_t []) { CAP_SYS_CHROOT, }, },
  102. [ZCAP_NICE] = { 1, (pvalue_t []) { CAP_SYS_NICE }, },
  103. [ZCAP_PTRACE] = { 1, (pvalue_t []) { CAP_SYS_PTRACE }, },
  104. [ZCAP_DAC_OVERRIDE] = { 1, (pvalue_t []) { CAP_DAC_OVERRIDE }, },
  105. [ZCAP_READ_SEARCH] = { 1, (pvalue_t []) { CAP_DAC_READ_SEARCH }, },
  106. [ZCAP_SYS_ADMIN] = { 1, (pvalue_t []) { CAP_SYS_ADMIN }, },
  107. [ZCAP_FOWNER] = { 1, (pvalue_t []) { CAP_FOWNER }, },
  108. #elif defined(HAVE_SOLARIS_CAPABILITIES) /* HAVE_LCAPS */
  109. /* Quagga -> Solaris privilege mappings */
  110. [ZCAP_SETID] = { 1, (pvalue_t []) { PRIV_PROC_SETID }, },
  111. [ZCAP_BIND] = { 1, (pvalue_t []) { PRIV_NET_PRIVADDR }, },
  112. /* IP_CONFIG is a subset of NET_CONFIG and is allowed in zones */
  113. #ifdef PRIV_SYS_IP_CONFIG
  114. [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_IP_CONFIG }, },
  115. #else
  116. [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_NET_CONFIG }, },
  117. #endif
  118. [ZCAP_NET_RAW] = { 2, (pvalue_t []) { PRIV_NET_RAWACCESS,
  119. PRIV_NET_ICMPACCESS }, },
  120. [ZCAP_CHROOT] = { 1, (pvalue_t []) { PRIV_PROC_CHROOT }, },
  121. [ZCAP_NICE] = { 1, (pvalue_t []) { PRIV_PROC_PRIOCNTL }, },
  122. [ZCAP_PTRACE] = { 1, (pvalue_t []) { PRIV_PROC_SESSION }, },
  123. [ZCAP_DAC_OVERRIDE] = { 4, (pvalue_t []) { PRIV_FILE_DAC_EXECUTE,
  124. PRIV_FILE_DAC_READ,
  125. PRIV_FILE_DAC_WRITE,
  126. PRIV_FILE_DAC_SEARCH }, },
  127. [ZCAP_READ_SEARCH] = { 2, (pvalue_t []) { PRIV_FILE_DAC_SEARCH,
  128. PRIV_FILE_DAC_READ }, },
  129. [ZCAP_SYS_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_ADMIN }, },
  130. [ZCAP_FOWNER] = { 1, (pvalue_t []) { PRIV_FILE_OWNER }, },
  131. #endif /* HAVE_SOLARIS_CAPABILITIES */
  132. };
  133. #ifdef HAVE_LCAPS
  134. /* Linux forms of capabilities methods */
  135. /* convert zebras privileges to system capabilities */
  136. static pset_t *
  137. zcaps2sys (zebra_capabilities_t *zcaps, int num)
  138. {
  139. pset_t *syscaps;
  140. int i, j = 0, count = 0;
  141. if (!num)
  142. return NULL;
  143. /* first count up how many system caps we have */
  144. for (i= 0; i < num; i++)
  145. count += cap_map[zcaps[i]].num;
  146. if ( (syscaps = XCALLOC (MTYPE_PRIVS, (sizeof(pset_t) * num))) == NULL)
  147. {
  148. fprintf (stderr, "%s: could not allocate syscaps!", __func__);
  149. return NULL;
  150. }
  151. syscaps->caps = XCALLOC (MTYPE_PRIVS, (sizeof (pvalue_t) * count));
  152. if (!syscaps->caps)
  153. {
  154. fprintf (stderr, "%s: could not XCALLOC caps!", __func__);
  155. return NULL;
  156. }
  157. /* copy the capabilities over */
  158. count = 0;
  159. for (i=0; i < num; i++)
  160. for (j = 0; j < cap_map[zcaps[i]].num; j++)
  161. syscaps->caps[count++] = cap_map[zcaps[i]].system_caps[j];
  162. /* iterations above should be exact same as previous count, obviously.. */
  163. syscaps->num = count;
  164. return syscaps;
  165. }
  166. /* set or clear the effective capabilities to/from permitted */
  167. int
  168. zprivs_change_caps (zebra_privs_ops_t op)
  169. {
  170. cap_flag_value_t cflag;
  171. /* should be no possibility of being called without valid caps */
  172. assert (zprivs_state.syscaps_p && zprivs_state.caps);
  173. if (! (zprivs_state.syscaps_p && zprivs_state.caps))
  174. exit (1);
  175. if (op == ZPRIVS_RAISE)
  176. cflag = CAP_SET;
  177. else if (op == ZPRIVS_LOWER)
  178. cflag = CAP_CLEAR;
  179. else
  180. return -1;
  181. if ( !cap_set_flag (zprivs_state.caps, CAP_EFFECTIVE,
  182. zprivs_state.syscaps_p->num,
  183. zprivs_state.syscaps_p->caps,
  184. cflag))
  185. return cap_set_proc (zprivs_state.caps);
  186. return -1;
  187. }
  188. zebra_privs_current_t
  189. zprivs_state_caps (void)
  190. {
  191. int i;
  192. cap_flag_value_t val;
  193. /* should be no possibility of being called without valid caps */
  194. assert (zprivs_state.syscaps_p && zprivs_state.caps);
  195. if (! (zprivs_state.syscaps_p && zprivs_state.caps))
  196. exit (1);
  197. for (i=0; i < zprivs_state.syscaps_p->num; i++)
  198. {
  199. if ( cap_get_flag (zprivs_state.caps, zprivs_state.syscaps_p->caps[i],
  200. CAP_EFFECTIVE, &val) )
  201. {
  202. zlog_warn ("zprivs_state_caps: could not cap_get_flag, %s",
  203. safe_strerror (errno) );
  204. return ZPRIVS_UNKNOWN;
  205. }
  206. if (val == CAP_SET)
  207. return ZPRIVS_RAISED;
  208. }
  209. return ZPRIVS_LOWERED;
  210. }
  211. static void
  212. zprivs_caps_init (struct zebra_privs_t *zprivs)
  213. {
  214. zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);
  215. zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i);
  216. /* Tell kernel we want caps maintained across uid changes */
  217. if ( prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1 )
  218. {
  219. fprintf (stderr, "privs_init: could not set PR_SET_KEEPCAPS, %s\n",
  220. safe_strerror (errno) );
  221. exit(1);
  222. }
  223. if ( !zprivs_state.syscaps_p )
  224. {
  225. fprintf (stderr, "privs_init: capabilities enabled, "
  226. "but no capabilities supplied\n");
  227. }
  228. /* we have caps, we have no need to ever change back the original user */
  229. if (zprivs_state.zuid)
  230. {
  231. if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
  232. {
  233. fprintf (stderr, "zprivs_init (cap): could not setreuid, %s\n",
  234. safe_strerror (errno));
  235. exit (1);
  236. }
  237. }
  238. if ( !(zprivs_state.caps = cap_init()) )
  239. {
  240. fprintf (stderr, "privs_init: failed to cap_init, %s\n",
  241. safe_strerror (errno));
  242. exit (1);
  243. }
  244. if ( cap_clear (zprivs_state.caps) )
  245. {
  246. fprintf (stderr, "privs_init: failed to cap_clear, %s\n",
  247. safe_strerror (errno));
  248. exit (1);
  249. }
  250. /* set permitted caps */
  251. cap_set_flag(zprivs_state.caps, CAP_PERMITTED,
  252. zprivs_state.syscaps_p->num,
  253. zprivs_state.syscaps_p->caps,
  254. CAP_SET);
  255. /* set inheritable caps, if any */
  256. if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num)
  257. {
  258. cap_set_flag(zprivs_state.caps, CAP_INHERITABLE,
  259. zprivs_state.syscaps_i->num,
  260. zprivs_state.syscaps_i->caps,
  261. CAP_SET);
  262. }
  263. /* apply caps. CAP_EFFECTIVE is cleared. we'll raise the caps as
  264. * and when, and only when, they are needed.
  265. */
  266. if ( cap_set_proc (zprivs_state.caps) )
  267. {
  268. cap_t current_caps;
  269. char *current_caps_text = NULL;
  270. char *wanted_caps_text = NULL;
  271. fprintf(stderr, "privs_init: initial cap_set_proc failed: %s\n",
  272. safe_strerror(errno));
  273. current_caps = cap_get_proc();
  274. if (current_caps)
  275. {
  276. current_caps_text = cap_to_text(current_caps, NULL);
  277. cap_free(current_caps);
  278. }
  279. wanted_caps_text = cap_to_text(zprivs_state.caps, NULL);
  280. fprintf(stderr, "Wanted caps: %s\n", wanted_caps_text ? wanted_caps_text : "???");
  281. fprintf(stderr, "Have caps: %s\n", current_caps_text ? current_caps_text : "???");
  282. if (current_caps_text)
  283. cap_free(current_caps_text);
  284. if (wanted_caps_text)
  285. cap_free(wanted_caps_text);
  286. exit (1);
  287. }
  288. /* set methods for the caller to use */
  289. zprivs->change = zprivs_change_caps;
  290. zprivs->current_state = zprivs_state_caps;
  291. }
  292. static void
  293. zprivs_caps_terminate (void)
  294. {
  295. /* clear all capabilities */
  296. if (zprivs_state.caps)
  297. cap_clear (zprivs_state.caps);
  298. /* and boom, capabilities are gone forever */
  299. if ( cap_set_proc (zprivs_state.caps) )
  300. {
  301. fprintf (stderr, "privs_terminate: cap_set_proc failed, %s",
  302. safe_strerror (errno) );
  303. exit (1);
  304. }
  305. /* free up private state */
  306. if (zprivs_state.syscaps_p->num)
  307. {
  308. XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p->caps);
  309. XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p);
  310. }
  311. if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num)
  312. {
  313. XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i->caps);
  314. XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i);
  315. }
  316. cap_free (zprivs_state.caps);
  317. }
  318. #elif defined (HAVE_SOLARIS_CAPABILITIES) /* !HAVE_LCAPS */
  319. /* Solaris specific capability/privilege methods
  320. *
  321. * Resources:
  322. * - the 'privileges' man page
  323. * - http://cvs.opensolaris.org
  324. * - http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1
  325. */
  326. static pset_t *
  327. zprivs_caps_minimal ()
  328. {
  329. pset_t *minimal;
  330. if ((minimal = priv_str_to_set("basic", ",", NULL)) == NULL)
  331. {
  332. fprintf (stderr, "%s: couldn't get basic set!\n", __func__);
  333. exit (1);
  334. }
  335. /* create a minimal privilege set from the basic set */
  336. (void) priv_delset(minimal, PRIV_PROC_EXEC);
  337. (void) priv_delset(minimal, PRIV_PROC_INFO);
  338. (void) priv_delset(minimal, PRIV_PROC_SESSION);
  339. (void) priv_delset(minimal, PRIV_FILE_LINK_ANY);
  340. return minimal;
  341. }
  342. /* convert zebras privileges to system capabilities */
  343. static pset_t *
  344. zcaps2sys (zebra_capabilities_t *zcaps, int num)
  345. {
  346. pset_t *syscaps;
  347. int i, j = 0;
  348. if ((syscaps = priv_allocset()) == NULL)
  349. {
  350. fprintf (stderr, "%s: could not allocate syscaps!\n", __func__);
  351. exit (1);
  352. }
  353. priv_emptyset (syscaps);
  354. for (i=0; i < num; i++)
  355. for (j = 0; j < cap_map[zcaps[i]].num; j++)
  356. priv_addset (syscaps, cap_map[zcaps[i]].system_caps[j]);
  357. return syscaps;
  358. }
  359. /* callback exported to users to RAISE and LOWER effective privileges
  360. * from nothing to the given permitted set and back down
  361. */
  362. int
  363. zprivs_change_caps (zebra_privs_ops_t op)
  364. {
  365. pset_t *privset;
  366. /* should be no possibility of being called without valid caps */
  367. assert (zprivs_state.syscaps_p);
  368. if (!zprivs_state.syscaps_p)
  369. {
  370. fprintf (stderr, "%s: Eek, missing privileged caps!", __func__);
  371. exit (1);
  372. }
  373. assert (zprivs_state.caps);
  374. if (!zprivs_state.caps)
  375. {
  376. fprintf (stderr, "%s: Eek, missing caps!", __func__);
  377. exit (1);
  378. }
  379. /* to raise: copy original permitted as our working effective set
  380. * to lower: copy regular effective set stored in zprivs_state.caps
  381. */
  382. if (op == ZPRIVS_RAISE)
  383. privset = zprivs_state.syscaps_p;
  384. else if (op == ZPRIVS_LOWER)
  385. privset = zprivs_state.caps;
  386. else
  387. return -1;
  388. if (setppriv (PRIV_SET, PRIV_EFFECTIVE, privset) != 0)
  389. return -1;
  390. return 0;
  391. }
  392. /* Retrieve current privilege state, is it RAISED or LOWERED? */
  393. zebra_privs_current_t
  394. zprivs_state_caps (void)
  395. {
  396. zebra_privs_current_t result;
  397. pset_t *effective;
  398. if ( (effective = priv_allocset()) == NULL)
  399. {
  400. fprintf (stderr, "%s: failed to get priv_allocset! %s\n", __func__,
  401. safe_strerror (errno));
  402. return ZPRIVS_UNKNOWN;
  403. }
  404. if (getppriv (PRIV_EFFECTIVE, effective))
  405. {
  406. fprintf (stderr, "%s: failed to get state! %s\n", __func__,
  407. safe_strerror (errno));
  408. result = ZPRIVS_UNKNOWN;
  409. }
  410. else
  411. {
  412. if (priv_isequalset (effective, zprivs_state.syscaps_p))
  413. result = ZPRIVS_RAISED;
  414. else if (priv_isequalset (effective, zprivs_state.caps))
  415. result = ZPRIVS_LOWERED;
  416. else
  417. result = ZPRIVS_UNKNOWN;
  418. }
  419. priv_freeset (effective);
  420. return result;
  421. }
  422. static void
  423. zprivs_caps_init (struct zebra_privs_t *zprivs)
  424. {
  425. pset_t *basic;
  426. pset_t *minimal;
  427. /* the specified sets */
  428. zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);
  429. zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i);
  430. /* nonsensical to have gotten here but not have capabilities */
  431. if (!zprivs_state.syscaps_p)
  432. {
  433. fprintf (stderr, "%s: capabilities enabled, "
  434. "but no valid capabilities supplied\n",
  435. __func__);
  436. }
  437. /* We retain the basic set in our permitted set, as Linux has no
  438. * equivalent. The basic set on Linux hence is implicit, always
  439. * there.
  440. */
  441. if ((basic = priv_str_to_set("basic", ",", NULL)) == NULL)
  442. {
  443. fprintf (stderr, "%s: couldn't get basic set!\n", __func__);
  444. exit (1);
  445. }
  446. /* Add the basic set to the permitted set */
  447. priv_union (basic, zprivs_state.syscaps_p);
  448. priv_freeset (basic);
  449. /* Hey kernel, we know about privileges!
  450. * this isn't strictly required, use of setppriv should have same effect
  451. */
  452. if (setpflags (PRIV_AWARE, 1))
  453. {
  454. fprintf (stderr, "%s: error setting PRIV_AWARE!, %s\n", __func__,
  455. safe_strerror (errno) );
  456. exit (1);
  457. }
  458. /* need either valid or empty sets for both p and i.. */
  459. assert (zprivs_state.syscaps_i && zprivs_state.syscaps_p);
  460. /* we have caps, we have no need to ever change back the original user
  461. * change real, effective and saved to the specified user.
  462. */
  463. if (zprivs_state.zuid)
  464. {
  465. if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
  466. {
  467. fprintf (stderr, "%s: could not setreuid, %s\n",
  468. __func__, safe_strerror (errno));
  469. exit (1);
  470. }
  471. }
  472. /* set the permitted set */
  473. if (setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.syscaps_p))
  474. {
  475. fprintf (stderr, "%s: error setting permitted set!, %s\n", __func__,
  476. safe_strerror (errno) );
  477. exit (1);
  478. }
  479. /* set the inheritable set */
  480. if (setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.syscaps_i))
  481. {
  482. fprintf (stderr, "%s: error setting inheritable set!, %s\n", __func__,
  483. safe_strerror (errno) );
  484. exit (1);
  485. }
  486. /* we need a minimal basic set for 'effective', potentially for inheritable too */
  487. minimal = zprivs_caps_minimal();
  488. /* now set the effective set with a subset of basic privileges */
  489. if (setppriv (PRIV_SET, PRIV_EFFECTIVE, minimal))
  490. {
  491. fprintf (stderr, "%s: error setting effective set!, %s\n", __func__,
  492. safe_strerror (errno) );
  493. exit (1);
  494. }
  495. /* we'll use the minimal set as our working-storage privset */
  496. zprivs_state.caps = minimal;
  497. /* set methods for the caller to use */
  498. zprivs->change = zprivs_change_caps;
  499. zprivs->current_state = zprivs_state_caps;
  500. }
  501. static void
  502. zprivs_caps_terminate (void)
  503. {
  504. assert (zprivs_state.caps);
  505. /* clear all capabilities by using working-storage privset */
  506. setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps);
  507. setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.caps);
  508. setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps);
  509. /* free up private state */
  510. if (zprivs_state.syscaps_p)
  511. priv_freeset (zprivs_state.syscaps_p);
  512. if (zprivs_state.syscaps_i)
  513. priv_freeset (zprivs_state.syscaps_i);
  514. priv_freeset (zprivs_state.caps);
  515. }
  516. #else /* !HAVE_LCAPS && ! HAVE_SOLARIS_CAPABILITIES */
  517. #error "Neither Solaris nor Linux capabilities, dazed and confused..."
  518. #endif /* HAVE_LCAPS */
  519. #endif /* HAVE_CAPABILITIES */
  520. int
  521. zprivs_change_uid (zebra_privs_ops_t op)
  522. {
  523. if (op == ZPRIVS_RAISE)
  524. return seteuid (zprivs_state.zsuid);
  525. else if (op == ZPRIVS_LOWER)
  526. return seteuid (zprivs_state.zuid);
  527. else
  528. return -1;
  529. }
  530. zebra_privs_current_t
  531. zprivs_state_uid (void)
  532. {
  533. return ( (zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED : ZPRIVS_RAISED);
  534. }
  535. int
  536. zprivs_change_null (zebra_privs_ops_t op)
  537. {
  538. return 0;
  539. }
  540. zebra_privs_current_t
  541. zprivs_state_null (void)
  542. {
  543. return zprivs_null_state;
  544. }
  545. #ifndef HAVE_GETGROUPLIST
  546. /* Solaris 11 has no getgrouplist() */
  547. static int
  548. getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
  549. {
  550. struct group *grp;
  551. size_t usridx;
  552. int pos = 0, ret;
  553. if (pos < *ngroups)
  554. groups[pos] = group;
  555. pos++;
  556. setgrent();
  557. while ((grp = getgrent()))
  558. {
  559. if (grp->gr_gid == group)
  560. continue;
  561. for (usridx = 0; grp->gr_mem[usridx] != NULL; usridx++)
  562. if (!strcmp (grp->gr_mem[usridx], user))
  563. {
  564. if (pos < *ngroups)
  565. groups[pos] = grp->gr_gid;
  566. pos++;
  567. break;
  568. }
  569. }
  570. endgrent();
  571. ret = (pos <= *ngroups) ? pos : -1;
  572. *ngroups = pos;
  573. return ret;
  574. }
  575. #endif /* HAVE_GETGROUPLIST */
  576. void
  577. zprivs_init(struct zebra_privs_t *zprivs)
  578. {
  579. struct passwd *pwentry = NULL;
  580. struct group *grentry = NULL;
  581. gid_t groups[NGROUPS_MAX];
  582. int i, ngroups = 0;
  583. int found = 0;
  584. if (!zprivs)
  585. {
  586. fprintf (stderr, "zprivs_init: called with NULL arg!\n");
  587. exit (1);
  588. }
  589. /* NULL privs */
  590. if (! (zprivs->user || zprivs->group
  591. || zprivs->cap_num_p || zprivs->cap_num_i) )
  592. {
  593. zprivs->change = zprivs_change_null;
  594. zprivs->current_state = zprivs_state_null;
  595. return;
  596. }
  597. if (zprivs->user)
  598. {
  599. if ( (pwentry = getpwnam (zprivs->user)) == NULL )
  600. {
  601. /* cant use log.h here as it depends on vty */
  602. fprintf (stderr, "privs_init: could not lookup user %s\n",
  603. zprivs->user);
  604. exit (1);
  605. }
  606. zprivs_state.zuid = pwentry->pw_uid;
  607. zprivs_state.zgid = pwentry->pw_gid;
  608. }
  609. grentry = NULL;
  610. if (zprivs->group)
  611. {
  612. if ( (grentry = getgrnam (zprivs->group)) == NULL )
  613. {
  614. fprintf (stderr, "privs_init: could not lookup group %s\n",
  615. zprivs->group);
  616. exit (1);
  617. }
  618. zprivs_state.zgid = grentry->gr_gid;
  619. }
  620. if (zprivs->user)
  621. {
  622. ngroups = sizeof(groups);
  623. if ( (ngroups = getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups )) < 0 )
  624. {
  625. /* cant use log.h here as it depends on vty */
  626. fprintf (stderr, "privs_init: could not getgrouplist for user %s\n",
  627. zprivs->user);
  628. exit (1);
  629. }
  630. }
  631. if (zprivs->vty_group)
  632. /* Add the vty_group to the supplementary groups so it can be chowned to */
  633. {
  634. if ( (grentry = getgrnam (zprivs->vty_group)) )
  635. {
  636. zprivs_state.vtygrp = grentry->gr_gid;
  637. for ( i = 0; i < ngroups; i++ )
  638. if ( groups[i] == zprivs_state.vtygrp )
  639. {
  640. found++;
  641. break;
  642. }
  643. if (!found)
  644. {
  645. fprintf (stderr, "privs_init: user(%s) is not part of vty group specified(%s)\n",
  646. zprivs->user, zprivs->vty_group);
  647. exit (1);
  648. }
  649. if ( i >= ngroups && ngroups < (int) ZEBRA_NUM_OF(groups) )
  650. {
  651. groups[i] = zprivs_state.vtygrp;
  652. }
  653. }
  654. else
  655. {
  656. fprintf (stderr, "privs_init: could not lookup vty group %s\n",
  657. zprivs->vty_group);
  658. exit (1);
  659. }
  660. }
  661. if (ngroups)
  662. {
  663. if ( setgroups (ngroups, groups) )
  664. {
  665. fprintf (stderr, "privs_init: could not setgroups, %s\n",
  666. safe_strerror (errno) );
  667. exit (1);
  668. }
  669. }
  670. if (zprivs_state.zgid)
  671. {
  672. /* change group now, forever. uid we do later */
  673. if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )
  674. {
  675. fprintf (stderr, "zprivs_init: could not setregid, %s\n",
  676. safe_strerror (errno) );
  677. exit (1);
  678. }
  679. }
  680. #ifdef HAVE_CAPABILITIES
  681. zprivs_caps_init (zprivs);
  682. #else /* !HAVE_CAPABILITIES */
  683. /* we dont have caps. we'll need to maintain rid and saved uid
  684. * and change euid back to saved uid (who we presume has all neccessary
  685. * privileges) whenever we are asked to raise our privileges.
  686. *
  687. * This is not worth that much security wise, but all we can do.
  688. */
  689. zprivs_state.zsuid = geteuid();
  690. if ( zprivs_state.zuid )
  691. {
  692. if ( setreuid (-1, zprivs_state.zuid) )
  693. {
  694. fprintf (stderr, "privs_init (uid): could not setreuid, %s\n",
  695. safe_strerror (errno));
  696. exit (1);
  697. }
  698. }
  699. zprivs->change = zprivs_change_uid;
  700. zprivs->current_state = zprivs_state_uid;
  701. #endif /* HAVE_CAPABILITIES */
  702. }
  703. void
  704. zprivs_terminate (struct zebra_privs_t *zprivs)
  705. {
  706. if (!zprivs)
  707. {
  708. fprintf (stderr, "%s: no privs struct given, terminating", __func__);
  709. exit (0);
  710. }
  711. #ifdef HAVE_CAPABILITIES
  712. zprivs_caps_terminate();
  713. #else /* !HAVE_CAPABILITIES */
  714. if (zprivs_state.zuid)
  715. {
  716. if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
  717. {
  718. fprintf (stderr, "privs_terminate: could not setreuid, %s",
  719. safe_strerror (errno) );
  720. exit (1);
  721. }
  722. }
  723. #endif /* HAVE_LCAPS */
  724. zprivs->change = zprivs_change_null;
  725. zprivs->current_state = zprivs_state_null;
  726. zprivs_null_state = ZPRIVS_LOWERED;
  727. return;
  728. }
  729. void
  730. zprivs_get_ids(struct zprivs_ids_t *ids)
  731. {
  732. ids->uid_priv = getuid();
  733. (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid)
  734. : (ids->uid_normal = -1);
  735. (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid)
  736. : (ids->gid_normal = -1);
  737. (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp)
  738. : (ids->gid_vty = -1);
  739. return;
  740. }