privs.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  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] = { 2, (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] = { 2, (pvalue_t []) { PRIV_FILE_DAC_EXECUTE,
  124. PRIV_FILE_DAC_READ,
  125. PRIV_FILE_DAC_SEARCH,
  126. PRIV_FILE_DAC_WRITE,
  127. PRIV_FILE_DAC_SEARCH }, },
  128. [ZCAP_READ_SEARCH] = { 2, (pvalue_t []) { PRIV_FILE_DAC_SEARCH,
  129. PRIV_FILE_DAC_READ }, },
  130. [ZCAP_SYS_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_ADMIN }, },
  131. [ZCAP_FOWNER] = { 1, (pvalue_t []) { PRIV_FILE_OWNER }, },
  132. #endif /* HAVE_SOLARIS_CAPABILITIES */
  133. };
  134. #ifdef HAVE_LCAPS
  135. /* Linux forms of capabilities methods */
  136. /* convert zebras privileges to system capabilities */
  137. static pset_t *
  138. zcaps2sys (zebra_capabilities_t *zcaps, int num)
  139. {
  140. pset_t *syscaps;
  141. int i, j = 0, count = 0;
  142. if (!num)
  143. return NULL;
  144. /* first count up how many system caps we have */
  145. for (i= 0; i < num; i++)
  146. count += cap_map[zcaps[i]].num;
  147. if ( (syscaps = XCALLOC (MTYPE_PRIVS, (sizeof(pset_t) * num))) == NULL)
  148. {
  149. fprintf (stderr, "%s: could not allocate syscaps!", __func__);
  150. return NULL;
  151. }
  152. syscaps->caps = XCALLOC (MTYPE_PRIVS, (sizeof (pvalue_t) * count));
  153. if (!syscaps->caps)
  154. {
  155. fprintf (stderr, "%s: could not XCALLOC caps!", __func__);
  156. return NULL;
  157. }
  158. /* copy the capabilities over */
  159. count = 0;
  160. for (i=0; i < num; i++)
  161. for (j = 0; j < cap_map[zcaps[i]].num; j++)
  162. syscaps->caps[count++] = cap_map[zcaps[i]].system_caps[j];
  163. /* iterations above should be exact same as previous count, obviously.. */
  164. syscaps->num = count;
  165. return syscaps;
  166. }
  167. /* set or clear the effective capabilities to/from permitted */
  168. int
  169. zprivs_change_caps (zebra_privs_ops_t op)
  170. {
  171. cap_flag_value_t cflag;
  172. /* should be no possibility of being called without valid caps */
  173. assert (zprivs_state.syscaps_p && zprivs_state.caps);
  174. if (! (zprivs_state.syscaps_p && zprivs_state.caps))
  175. exit (1);
  176. if (op == ZPRIVS_RAISE)
  177. cflag = CAP_SET;
  178. else if (op == ZPRIVS_LOWER)
  179. cflag = CAP_CLEAR;
  180. else
  181. return -1;
  182. if ( !cap_set_flag (zprivs_state.caps, CAP_EFFECTIVE,
  183. zprivs_state.syscaps_p->num,
  184. zprivs_state.syscaps_p->caps,
  185. cflag))
  186. return cap_set_proc (zprivs_state.caps);
  187. return -1;
  188. }
  189. zebra_privs_current_t
  190. zprivs_state_caps (void)
  191. {
  192. int i;
  193. cap_flag_value_t val;
  194. /* should be no possibility of being called without valid caps */
  195. assert (zprivs_state.syscaps_p && zprivs_state.caps);
  196. if (! (zprivs_state.syscaps_p && zprivs_state.caps))
  197. exit (1);
  198. for (i=0; i < zprivs_state.syscaps_p->num; i++)
  199. {
  200. if ( cap_get_flag (zprivs_state.caps, zprivs_state.syscaps_p->caps[i],
  201. CAP_EFFECTIVE, &val) )
  202. {
  203. zlog_warn ("zprivs_state_caps: could not cap_get_flag, %s",
  204. safe_strerror (errno) );
  205. return ZPRIVS_UNKNOWN;
  206. }
  207. if (val == CAP_SET)
  208. return ZPRIVS_RAISED;
  209. }
  210. return ZPRIVS_LOWERED;
  211. }
  212. static void
  213. zprivs_caps_init (struct zebra_privs_t *zprivs)
  214. {
  215. zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);
  216. zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i);
  217. /* Tell kernel we want caps maintained across uid changes */
  218. if ( prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1 )
  219. {
  220. fprintf (stderr, "privs_init: could not set PR_SET_KEEPCAPS, %s\n",
  221. safe_strerror (errno) );
  222. exit(1);
  223. }
  224. if ( !zprivs_state.syscaps_p )
  225. {
  226. fprintf (stderr, "privs_init: capabilities enabled, "
  227. "but no capabilities supplied\n");
  228. }
  229. /* we have caps, we have no need to ever change back the original user */
  230. if (zprivs_state.zuid)
  231. {
  232. if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
  233. {
  234. fprintf (stderr, "zprivs_init (cap): could not setreuid, %s\n",
  235. safe_strerror (errno));
  236. exit (1);
  237. }
  238. }
  239. if ( !(zprivs_state.caps = cap_init()) )
  240. {
  241. fprintf (stderr, "privs_init: failed to cap_init, %s\n",
  242. safe_strerror (errno));
  243. exit (1);
  244. }
  245. if ( cap_clear (zprivs_state.caps) )
  246. {
  247. fprintf (stderr, "privs_init: failed to cap_clear, %s\n",
  248. safe_strerror (errno));
  249. exit (1);
  250. }
  251. /* set permitted caps */
  252. cap_set_flag(zprivs_state.caps, CAP_PERMITTED,
  253. zprivs_state.syscaps_p->num,
  254. zprivs_state.syscaps_p->caps,
  255. CAP_SET);
  256. /* set inheritable caps, if any */
  257. if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num)
  258. {
  259. cap_set_flag(zprivs_state.caps, CAP_INHERITABLE,
  260. zprivs_state.syscaps_i->num,
  261. zprivs_state.syscaps_i->caps,
  262. CAP_SET);
  263. }
  264. /* apply caps. CAP_EFFECTIVE is cleared. we'll raise the caps as
  265. * and when, and only when, they are needed.
  266. */
  267. if ( cap_set_proc (zprivs_state.caps) )
  268. {
  269. cap_t current_caps;
  270. char *current_caps_text = NULL;
  271. char *wanted_caps_text = NULL;
  272. fprintf(stderr, "privs_init: initial cap_set_proc failed: %s\n",
  273. safe_strerror(errno));
  274. current_caps = cap_get_proc();
  275. if (current_caps)
  276. {
  277. current_caps_text = cap_to_text(current_caps, NULL);
  278. cap_free(current_caps);
  279. }
  280. wanted_caps_text = cap_to_text(zprivs_state.caps, NULL);
  281. fprintf(stderr, "Wanted caps: %s\n", wanted_caps_text ? wanted_caps_text : "???");
  282. fprintf(stderr, "Have caps: %s\n", current_caps_text ? current_caps_text : "???");
  283. if (current_caps_text)
  284. cap_free(current_caps_text);
  285. if (wanted_caps_text)
  286. cap_free(wanted_caps_text);
  287. exit (1);
  288. }
  289. /* set methods for the caller to use */
  290. zprivs->change = zprivs_change_caps;
  291. zprivs->current_state = zprivs_state_caps;
  292. }
  293. static void
  294. zprivs_caps_terminate (void)
  295. {
  296. /* clear all capabilities */
  297. if (zprivs_state.caps)
  298. cap_clear (zprivs_state.caps);
  299. /* and boom, capabilities are gone forever */
  300. if ( cap_set_proc (zprivs_state.caps) )
  301. {
  302. fprintf (stderr, "privs_terminate: cap_set_proc failed, %s",
  303. safe_strerror (errno) );
  304. exit (1);
  305. }
  306. /* free up private state */
  307. if (zprivs_state.syscaps_p->num)
  308. {
  309. XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p->caps);
  310. XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p);
  311. }
  312. if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num)
  313. {
  314. XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i->caps);
  315. XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i);
  316. }
  317. cap_free (zprivs_state.caps);
  318. }
  319. #elif defined (HAVE_SOLARIS_CAPABILITIES) /* !HAVE_LCAPS */
  320. /* Solaris specific capability/privilege methods
  321. *
  322. * Resources:
  323. * - the 'privileges' man page
  324. * - http://cvs.opensolaris.org
  325. * - http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1
  326. */
  327. static pset_t *
  328. zprivs_caps_minimal ()
  329. {
  330. pset_t *minimal;
  331. if ((minimal = priv_str_to_set("basic", ",", NULL)) == NULL)
  332. {
  333. fprintf (stderr, "%s: couldn't get basic set!\n", __func__);
  334. exit (1);
  335. }
  336. /* create a minimal privilege set from the basic set */
  337. (void) priv_delset(minimal, PRIV_PROC_EXEC);
  338. (void) priv_delset(minimal, PRIV_PROC_INFO);
  339. (void) priv_delset(minimal, PRIV_PROC_SESSION);
  340. (void) priv_delset(minimal, PRIV_FILE_LINK_ANY);
  341. return minimal;
  342. }
  343. /* convert zebras privileges to system capabilities */
  344. static pset_t *
  345. zcaps2sys (zebra_capabilities_t *zcaps, int num)
  346. {
  347. pset_t *syscaps;
  348. int i, j = 0;
  349. if ((syscaps = priv_allocset()) == NULL)
  350. {
  351. fprintf (stderr, "%s: could not allocate syscaps!\n", __func__);
  352. exit (1);
  353. }
  354. priv_emptyset (syscaps);
  355. for (i=0; i < num; i++)
  356. for (j = 0; j < cap_map[zcaps[i]].num; j++)
  357. priv_addset (syscaps, cap_map[zcaps[i]].system_caps[j]);
  358. return syscaps;
  359. }
  360. /* callback exported to users to RAISE and LOWER effective privileges
  361. * from nothing to the given permitted set and back down
  362. */
  363. int
  364. zprivs_change_caps (zebra_privs_ops_t op)
  365. {
  366. pset_t *privset;
  367. /* should be no possibility of being called without valid caps */
  368. assert (zprivs_state.syscaps_p);
  369. if (!zprivs_state.syscaps_p)
  370. {
  371. fprintf (stderr, "%s: Eek, missing privileged caps!", __func__);
  372. exit (1);
  373. }
  374. assert (zprivs_state.caps);
  375. if (!zprivs_state.caps)
  376. {
  377. fprintf (stderr, "%s: Eek, missing caps!", __func__);
  378. exit (1);
  379. }
  380. /* to raise: copy original permitted as our working effective set
  381. * to lower: copy regular effective set stored in zprivs_state.caps
  382. */
  383. if (op == ZPRIVS_RAISE)
  384. privset = zprivs_state.syscaps_p;
  385. else if (op == ZPRIVS_LOWER)
  386. privset = zprivs_state.caps;
  387. else
  388. return -1;
  389. if (setppriv (PRIV_SET, PRIV_EFFECTIVE, privset) != 0)
  390. return -1;
  391. return 0;
  392. }
  393. /* Retrieve current privilege state, is it RAISED or LOWERED? */
  394. zebra_privs_current_t
  395. zprivs_state_caps (void)
  396. {
  397. zebra_privs_current_t result;
  398. pset_t *effective;
  399. if ( (effective = priv_allocset()) == NULL)
  400. {
  401. fprintf (stderr, "%s: failed to get priv_allocset! %s\n", __func__,
  402. safe_strerror (errno));
  403. return ZPRIVS_UNKNOWN;
  404. }
  405. if (getppriv (PRIV_EFFECTIVE, effective))
  406. {
  407. fprintf (stderr, "%s: failed to get state! %s\n", __func__,
  408. safe_strerror (errno));
  409. result = ZPRIVS_UNKNOWN;
  410. }
  411. else
  412. {
  413. if (priv_isequalset (effective, zprivs_state.syscaps_p))
  414. result = ZPRIVS_RAISED;
  415. else if (priv_isequalset (effective, zprivs_state.caps))
  416. result = ZPRIVS_LOWERED;
  417. else
  418. result = ZPRIVS_UNKNOWN;
  419. }
  420. priv_freeset (effective);
  421. return result;
  422. }
  423. static void
  424. zprivs_caps_init (struct zebra_privs_t *zprivs)
  425. {
  426. pset_t *basic;
  427. pset_t *minimal;
  428. /* the specified sets */
  429. zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);
  430. zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i);
  431. /* nonsensical to have gotten here but not have capabilities */
  432. if (!zprivs_state.syscaps_p)
  433. {
  434. fprintf (stderr, "%s: capabilities enabled, "
  435. "but no valid capabilities supplied\n",
  436. __func__);
  437. }
  438. /* We retain the basic set in our permitted set, as Linux has no
  439. * equivalent. The basic set on Linux hence is implicit, always
  440. * there.
  441. */
  442. if ((basic = priv_str_to_set("basic", ",", NULL)) == NULL)
  443. {
  444. fprintf (stderr, "%s: couldn't get basic set!\n", __func__);
  445. exit (1);
  446. }
  447. /* Add the basic set to the permitted set */
  448. priv_union (basic, zprivs_state.syscaps_p);
  449. priv_freeset (basic);
  450. /* Hey kernel, we know about privileges!
  451. * this isn't strictly required, use of setppriv should have same effect
  452. */
  453. if (setpflags (PRIV_AWARE, 1))
  454. {
  455. fprintf (stderr, "%s: error setting PRIV_AWARE!, %s\n", __func__,
  456. safe_strerror (errno) );
  457. exit (1);
  458. }
  459. /* need either valid or empty sets for both p and i.. */
  460. assert (zprivs_state.syscaps_i && zprivs_state.syscaps_p);
  461. /* we have caps, we have no need to ever change back the original user
  462. * change real, effective and saved to the specified user.
  463. */
  464. if (zprivs_state.zuid)
  465. {
  466. if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
  467. {
  468. fprintf (stderr, "%s: could not setreuid, %s\n",
  469. __func__, safe_strerror (errno));
  470. exit (1);
  471. }
  472. }
  473. /* set the permitted set */
  474. if (setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.syscaps_p))
  475. {
  476. fprintf (stderr, "%s: error setting permitted set!, %s\n", __func__,
  477. safe_strerror (errno) );
  478. exit (1);
  479. }
  480. /* set the inheritable set */
  481. if (setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.syscaps_i))
  482. {
  483. fprintf (stderr, "%s: error setting inheritable set!, %s\n", __func__,
  484. safe_strerror (errno) );
  485. exit (1);
  486. }
  487. /* we need a minimal basic set for 'effective', potentially for inheritable too */
  488. minimal = zprivs_caps_minimal();
  489. /* now set the effective set with a subset of basic privileges */
  490. if (setppriv (PRIV_SET, PRIV_EFFECTIVE, minimal))
  491. {
  492. fprintf (stderr, "%s: error setting effective set!, %s\n", __func__,
  493. safe_strerror (errno) );
  494. exit (1);
  495. }
  496. /* we'll use the minimal set as our working-storage privset */
  497. zprivs_state.caps = minimal;
  498. /* set methods for the caller to use */
  499. zprivs->change = zprivs_change_caps;
  500. zprivs->current_state = zprivs_state_caps;
  501. }
  502. static void
  503. zprivs_caps_terminate (void)
  504. {
  505. assert (zprivs_state.caps);
  506. /* clear all capabilities by using working-storage privset */
  507. setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps);
  508. setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.caps);
  509. setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps);
  510. /* free up private state */
  511. if (zprivs_state.syscaps_p)
  512. priv_freeset (zprivs_state.syscaps_p);
  513. if (zprivs_state.syscaps_i)
  514. priv_freeset (zprivs_state.syscaps_i);
  515. priv_freeset (zprivs_state.caps);
  516. }
  517. #else /* !HAVE_LCAPS && ! HAVE_SOLARIS_CAPABILITIES */
  518. #error "Neither Solaris nor Linux capabilities, dazed and confused..."
  519. #endif /* HAVE_LCAPS */
  520. #endif /* HAVE_CAPABILITIES */
  521. int
  522. zprivs_change_uid (zebra_privs_ops_t op)
  523. {
  524. if (op == ZPRIVS_RAISE)
  525. return seteuid (zprivs_state.zsuid);
  526. else if (op == ZPRIVS_LOWER)
  527. return seteuid (zprivs_state.zuid);
  528. else
  529. return -1;
  530. }
  531. zebra_privs_current_t
  532. zprivs_state_uid (void)
  533. {
  534. return ( (zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED : ZPRIVS_RAISED);
  535. }
  536. int
  537. zprivs_change_null (zebra_privs_ops_t op)
  538. {
  539. return 0;
  540. }
  541. zebra_privs_current_t
  542. zprivs_state_null (void)
  543. {
  544. return zprivs_null_state;
  545. }
  546. #ifndef HAVE_GETGROUPLIST
  547. /* Solaris 11 has no getgrouplist() */
  548. static int
  549. getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
  550. {
  551. struct group *grp;
  552. size_t usridx;
  553. int pos = 0, ret;
  554. if (pos < *ngroups)
  555. groups[pos] = group;
  556. pos++;
  557. setgrent();
  558. while ((grp = getgrent()))
  559. {
  560. if (grp->gr_gid == group)
  561. continue;
  562. for (usridx = 0; grp->gr_mem[usridx] != NULL; usridx++)
  563. if (!strcmp (grp->gr_mem[usridx], user))
  564. {
  565. if (pos < *ngroups)
  566. groups[pos] = grp->gr_gid;
  567. pos++;
  568. break;
  569. }
  570. }
  571. endgrent();
  572. ret = (pos <= *ngroups) ? pos : -1;
  573. *ngroups = pos;
  574. return ret;
  575. }
  576. #endif /* HAVE_GETGROUPLIST */
  577. void
  578. zprivs_init(struct zebra_privs_t *zprivs)
  579. {
  580. struct passwd *pwentry = NULL;
  581. struct group *grentry = NULL;
  582. gid_t groups[NGROUPS_MAX];
  583. int i, ngroups = 0;
  584. int found = 0;
  585. if (!zprivs)
  586. {
  587. fprintf (stderr, "zprivs_init: called with NULL arg!\n");
  588. exit (1);
  589. }
  590. /* NULL privs */
  591. if (! (zprivs->user || zprivs->group
  592. || zprivs->cap_num_p || zprivs->cap_num_i) )
  593. {
  594. zprivs->change = zprivs_change_null;
  595. zprivs->current_state = zprivs_state_null;
  596. return;
  597. }
  598. if (zprivs->user)
  599. {
  600. if ( (pwentry = getpwnam (zprivs->user)) == NULL )
  601. {
  602. /* cant use log.h here as it depends on vty */
  603. fprintf (stderr, "privs_init: could not lookup user %s\n",
  604. zprivs->user);
  605. exit (1);
  606. }
  607. zprivs_state.zuid = pwentry->pw_uid;
  608. zprivs_state.zgid = pwentry->pw_gid;
  609. }
  610. grentry = NULL;
  611. if (zprivs->group)
  612. {
  613. if ( (grentry = getgrnam (zprivs->group)) == NULL )
  614. {
  615. fprintf (stderr, "privs_init: could not lookup group %s\n",
  616. zprivs->group);
  617. exit (1);
  618. }
  619. zprivs_state.zgid = grentry->gr_gid;
  620. }
  621. if (zprivs->user)
  622. {
  623. ngroups = sizeof(groups);
  624. if ( (ngroups = getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups )) < 0 )
  625. {
  626. /* cant use log.h here as it depends on vty */
  627. fprintf (stderr, "privs_init: could not getgrouplist for user %s\n",
  628. zprivs->user);
  629. exit (1);
  630. }
  631. }
  632. if (zprivs->vty_group)
  633. /* Add the vty_group to the supplementary groups so it can be chowned to */
  634. {
  635. if ( (grentry = getgrnam (zprivs->vty_group)) )
  636. {
  637. zprivs_state.vtygrp = grentry->gr_gid;
  638. for ( i = 0; i < ngroups; i++ )
  639. if ( groups[i] == zprivs_state.vtygrp )
  640. {
  641. found++;
  642. break;
  643. }
  644. if (!found)
  645. {
  646. fprintf (stderr, "privs_init: user(%s) is not part of vty group specified(%s)\n",
  647. zprivs->user, zprivs->vty_group);
  648. exit (1);
  649. }
  650. if ( i >= ngroups && ngroups < (int) ZEBRA_NUM_OF(groups) )
  651. {
  652. groups[i] = zprivs_state.vtygrp;
  653. }
  654. }
  655. else
  656. {
  657. fprintf (stderr, "privs_init: could not lookup vty group %s\n",
  658. zprivs->vty_group);
  659. exit (1);
  660. }
  661. }
  662. if (ngroups)
  663. {
  664. if ( setgroups (ngroups, groups) )
  665. {
  666. fprintf (stderr, "privs_init: could not setgroups, %s\n",
  667. safe_strerror (errno) );
  668. exit (1);
  669. }
  670. }
  671. if (zprivs_state.zgid)
  672. {
  673. /* change group now, forever. uid we do later */
  674. if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )
  675. {
  676. fprintf (stderr, "zprivs_init: could not setregid, %s\n",
  677. safe_strerror (errno) );
  678. exit (1);
  679. }
  680. }
  681. #ifdef HAVE_CAPABILITIES
  682. zprivs_caps_init (zprivs);
  683. #else /* !HAVE_CAPABILITIES */
  684. /* we dont have caps. we'll need to maintain rid and saved uid
  685. * and change euid back to saved uid (who we presume has all neccessary
  686. * privileges) whenever we are asked to raise our privileges.
  687. *
  688. * This is not worth that much security wise, but all we can do.
  689. */
  690. zprivs_state.zsuid = geteuid();
  691. if ( zprivs_state.zuid )
  692. {
  693. if ( setreuid (-1, zprivs_state.zuid) )
  694. {
  695. fprintf (stderr, "privs_init (uid): could not setreuid, %s\n",
  696. safe_strerror (errno));
  697. exit (1);
  698. }
  699. }
  700. zprivs->change = zprivs_change_uid;
  701. zprivs->current_state = zprivs_state_uid;
  702. #endif /* HAVE_CAPABILITIES */
  703. }
  704. void
  705. zprivs_terminate (struct zebra_privs_t *zprivs)
  706. {
  707. if (!zprivs)
  708. {
  709. fprintf (stderr, "%s: no privs struct given, terminating", __func__);
  710. exit (0);
  711. }
  712. #ifdef HAVE_CAPABILITIES
  713. zprivs_caps_terminate();
  714. #else /* !HAVE_CAPABILITIES */
  715. if (zprivs_state.zuid)
  716. {
  717. if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
  718. {
  719. fprintf (stderr, "privs_terminate: could not setreuid, %s",
  720. safe_strerror (errno) );
  721. exit (1);
  722. }
  723. }
  724. #endif /* HAVE_LCAPS */
  725. zprivs->change = zprivs_change_null;
  726. zprivs->current_state = zprivs_state_null;
  727. zprivs_null_state = ZPRIVS_LOWERED;
  728. return;
  729. }
  730. void
  731. zprivs_get_ids(struct zprivs_ids_t *ids)
  732. {
  733. ids->uid_priv = getuid();
  734. (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid)
  735. : (ids->uid_normal = -1);
  736. (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid)
  737. : (ids->gid_normal = -1);
  738. (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp)
  739. : (ids->gid_vty = -1);
  740. return;
  741. }