Skip to content

Commit 436300f

Browse files
committed
pivy-box: support finding templates at multiple paths
Including a system path in /etc so that there can be system-wide templates. This also allows us to use more "native" feeling dirs on OS like Linux and MacOS.
1 parent f9683bf commit 436300f

File tree

6 files changed

+377
-64
lines changed

6 files changed

+377
-64
lines changed

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ ifeq ($(SYSTEM), Linux)
6767
PAM_LIBS = -lpam
6868
PAM_PLUGINDIR ?= $(libdir)/security
6969
SYSTEMDDIR ?= $(libdir)/systemd/user
70+
tpl_user_dir ?= "$$HOME/.config/pivy/tpl/$$TPL"
71+
tpl_system_dir ?= "/etc/pivy/tpl/$$TPL"
7072
endif
7173
ifeq ($(SYSTEM), OpenBSD)
7274
PCSC_CFLAGS = $(shell pkg-config --cflags libpcsclite)
@@ -98,6 +100,8 @@ ifeq ($(SYSTEM), Darwin)
98100
RDLINE_LIBS = -ledit
99101
HAVE_ZFS := no
100102
HAVE_PAM := no
103+
tpl_user_dir ?= "$$HOME/Library/Preferences/pivy/tpl/$$TPL"
104+
tpl_system_dir ?= "/Library/Preferences/pivy/tpl/$$TPL"
101105
endif
102106
ifeq ($(SYSTEM), SunOS)
103107
PCSC_CFLAGS = $(shell pkg-config --cflags libpcsclite)
@@ -119,6 +123,12 @@ ifeq ($(SYSTEM), SunOS)
119123
endif
120124
LIBCRYPTO ?= $(LIBRESSL_LIB)/libcrypto.a
121125

126+
tpl_user_dir ?= "$$HOME/.pivy/tpl/$$TPL"
127+
tpl_system_dir ?= "/etc/pivy/tpl/$$TPL"
128+
129+
CONFIG_CFLAGS = -DEBOX_USER_TPL_PATH='$(tpl_user_dir)'
130+
CONFIG_CFLAGS += -DEBOX_SYSTEM_TPL_PATH='$(tpl_system_dir)'
131+
122132
_ED25519_SOURCES= \
123133
ed25519.c \
124134
fe25519.c \
@@ -194,6 +204,7 @@ PIVTOOL_CFLAGS= $(PCSC_CFLAGS) \
194204
$(ZLIB_CFLAGS) \
195205
$(SYSTEM_CFLAGS) \
196206
$(SECURITY_CFLAGS) \
207+
$(CONFIG_CFLAGS) \
197208
-O2 -g -D_GNU_SOURCE \
198209
-DPIVY_VERSION='"$(VERSION)"'
199210
PIVTOOL_LDFLAGS= $(SYSTEM_LDFLAGS)
@@ -226,6 +237,7 @@ PIVYBOX_CFLAGS= $(PCSC_CFLAGS) \
226237
$(ZLIB_CFLAGS) \
227238
$(RDLINE_CFLAGS) \
228239
$(SYSTEM_CFLAGS) \
240+
$(CONFIG_CFLAGS) \
229241
$(SECURITY_CFLAGS) \
230242
-O2 -g -D_GNU_SOURCE -std=gnu99
231243
PIVYBOX_LDFLAGS= $(SYSTEM_LDFLAGS)
@@ -263,6 +275,7 @@ PIVZFS_CFLAGS= $(PCSC_CFLAGS) \
263275
$(LIBZFS_CFLAGS) \
264276
$(RDLINE_CFLAGS) \
265277
$(SYSTEM_CFLAGS) \
278+
$(CONFIG_CFLAGS) \
266279
$(SECURITY_CFLAGS) \
267280
-O2 -g -D_GNU_SOURCE -std=gnu99
268281
PIVZFS_LDFLAGS= $(SYSTEM_LDFLAGS)
@@ -310,6 +323,7 @@ PIVYLUKS_CFLAGS= $(PCSC_CFLAGS) \
310323
$(JSONC_CFLAGS) \
311324
$(RDLINE_CFLAGS) \
312325
$(SYSTEM_CFLAGS) \
326+
$(CONFIG_CFLAGS) \
313327
$(SECURITY_CFLAGS) \
314328
-O2 -g -D_GNU_SOURCE -std=gnu99
315329
PIVYLUKS_LDFLAGS= $(SYSTEM_LDFLAGS)
@@ -353,6 +367,7 @@ PAMPIVY_CFLAGS= $(PCSC_CFLAGS) \
353367
$(ZLIB_CFLAGS) \
354368
$(PAM_CFLAGS) \
355369
$(SYSTEM_CFLAGS) \
370+
$(CONFIG_CFLAGS) \
356371
$(SECURITY_CFLAGS) \
357372
-O2 -g -D_GNU_SOURCE -std=gnu99
358373
PAMPIVY_LDFLAGS= $(SYSTEM_LDFLAGS)
@@ -393,6 +408,7 @@ AGENT_CFLAGS= $(PCSC_CFLAGS) \
393408
$(CRYPTO_CFLAGS) \
394409
$(ZLIB_CFLAGS) \
395410
$(SYSTEM_CFLAGS) \
411+
$(CONFIG_CFLAGS) \
396412
$(SECURITY_CFLAGS) \
397413
-O2 -g -D_GNU_SOURCE
398414
AGENT_LDFLAGS= $(SYSTEM_LDFLAGS)

ebox-cmd.c

Lines changed: 232 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@
6060

6161
#include "words.h"
6262

63+
#if !defined(EBOX_USER_TPL_PATH)
64+
#define EBOX_USER_TPL_PATH "$HOME/.pivy/tpl/$TPL"
65+
#endif
66+
#if !defined(EBOX_SYSTEM_TPL_PATH)
67+
#define EBOX_SYSTEM_TPL_PATH "/etc/pivy/tpl/$TPL"
68+
#endif
69+
6370
int ebox_authfd = -1;
6471
SCARDCONTEXT ebox_ctx;
6572
boolean_t ebox_ctx_init = B_FALSE;
@@ -1058,6 +1065,229 @@ interactive_recovery(struct ebox_config *config, const char *what)
10581065
return (NULL);
10591066
}
10601067

1068+
struct ebox_tpl_path_ent *ebox_tpl_path = NULL;
1069+
1070+
static struct ebox_tpl_path_seg *
1071+
parse_tpl_path_segs(const char *path)
1072+
{
1073+
struct ebox_tpl_path_seg *seg, *first = NULL, *last = NULL;
1074+
const char *basep, *p;
1075+
size_t n;
1076+
1077+
p = path;
1078+
basep = NULL;
1079+
1080+
while (1) {
1081+
if (*p == '$' || *p == '\0') {
1082+
/* end current segment */
1083+
if (basep != NULL) {
1084+
seg = calloc(1, sizeof (*seg));
1085+
seg->tps_type = PATH_SEG_FIXED;
1086+
n = p - basep;
1087+
seg->tps_fixed = malloc(n + 1);
1088+
strncpy(seg->tps_fixed, basep, n);
1089+
if (first == NULL)
1090+
first = seg;
1091+
if (last != NULL)
1092+
last->tps_next = seg;
1093+
last = seg;
1094+
basep = NULL;
1095+
}
1096+
if (*p == '$') {
1097+
if (strncmp(p, "$TPL", 4) == 0) {
1098+
p += 4;
1099+
seg = calloc(1, sizeof (*seg));
1100+
seg->tps_type = PATH_SEG_TPL;
1101+
if (first == NULL)
1102+
first = seg;
1103+
if (last != NULL)
1104+
last->tps_next = seg;
1105+
last = seg;
1106+
continue;
1107+
}
1108+
basep = ++p;
1109+
while (*p != '\0' && (
1110+
(*p >= 'A' && *p <= 'Z') ||
1111+
(*p >= 'a' && *p <= 'z') ||
1112+
(*p >= '0' && *p <= '9'))) {
1113+
++p;
1114+
}
1115+
seg = calloc(1, sizeof (*seg));
1116+
seg->tps_type = PATH_SEG_ENV;
1117+
n = p - basep;
1118+
seg->tps_env = malloc(n + 1);
1119+
strncpy(seg->tps_fixed, basep, n);
1120+
if (first == NULL)
1121+
first = seg;
1122+
if (last != NULL)
1123+
last->tps_next = seg;
1124+
last = seg;
1125+
basep = NULL;
1126+
} else {
1127+
break;
1128+
}
1129+
} else {
1130+
if (basep == NULL)
1131+
basep = p;
1132+
++p;
1133+
}
1134+
}
1135+
1136+
return (first);
1137+
}
1138+
1139+
void
1140+
parse_tpl_path_env(void)
1141+
{
1142+
struct ebox_tpl_path_ent *tpe, *last = NULL;
1143+
const char *env;
1144+
char *tmp;
1145+
char *token, *saveptr = NULL;
1146+
1147+
tpe = calloc(1, sizeof (*tpe));
1148+
if (ebox_tpl_path == NULL)
1149+
ebox_tpl_path = tpe;
1150+
if (last != NULL)
1151+
last->tpe_next = tpe;
1152+
tpe->tpe_path_tpl = strdup(EBOX_USER_TPL_PATH);
1153+
tpe->tpe_segs = parse_tpl_path_segs(tpe->tpe_path_tpl);
1154+
last = tpe;
1155+
1156+
#if !defined(NO_LEGACY_EBOX_TPL_PATH)
1157+
tpe = calloc(1, sizeof (*tpe));
1158+
if (ebox_tpl_path == NULL)
1159+
ebox_tpl_path = tpe;
1160+
if (last != NULL)
1161+
last->tpe_next = tpe;
1162+
tpe->tpe_path_tpl = strdup("$HOME/.ebox/tpl/$TPL");
1163+
tpe->tpe_segs = parse_tpl_path_segs(tpe->tpe_path_tpl);
1164+
last = tpe;
1165+
#endif
1166+
1167+
env = getenv("PIVY_EBOX_TPL_PATH");
1168+
if (env != NULL) {
1169+
tmp = strdup(env);
1170+
1171+
while (1) {
1172+
token = strtok_r(tmp, ":", &saveptr);
1173+
if (token == NULL)
1174+
break;
1175+
tmp = NULL;
1176+
1177+
tpe = calloc(1, sizeof (*tpe));
1178+
if (ebox_tpl_path == NULL)
1179+
ebox_tpl_path = tpe;
1180+
if (last != NULL)
1181+
last->tpe_next = tpe;
1182+
tpe->tpe_path_tpl = strdup(token);
1183+
tpe->tpe_segs = parse_tpl_path_segs(tpe->tpe_path_tpl);
1184+
last = tpe;
1185+
}
1186+
}
1187+
1188+
tpe = calloc(1, sizeof (*tpe));
1189+
if (ebox_tpl_path == NULL)
1190+
ebox_tpl_path = tpe;
1191+
if (last != NULL)
1192+
last->tpe_next = tpe;
1193+
tpe->tpe_path_tpl = strdup(EBOX_SYSTEM_TPL_PATH);
1194+
tpe->tpe_segs = parse_tpl_path_segs(tpe->tpe_path_tpl);
1195+
last = tpe;
1196+
}
1197+
1198+
char *
1199+
compose_path(const struct ebox_tpl_path_seg *segs, const char *tpl)
1200+
{
1201+
char *buf;
1202+
const char *tmp;
1203+
const struct ebox_tpl_path_seg *seg;
1204+
1205+
buf = malloc(PATH_MAX);
1206+
buf[0] = '\0';
1207+
1208+
seg = segs;
1209+
while (seg != NULL) {
1210+
switch (seg->tps_type) {
1211+
case PATH_SEG_FIXED:
1212+
strlcat(buf, seg->tps_fixed, PATH_MAX);
1213+
break;
1214+
case PATH_SEG_ENV:
1215+
tmp = getenv(seg->tps_env);
1216+
if (tmp != NULL)
1217+
strlcat(buf, tmp, PATH_MAX);
1218+
break;
1219+
case PATH_SEG_TPL:
1220+
strlcat(buf, tpl, PATH_MAX);
1221+
break;
1222+
}
1223+
seg = seg->tps_next;
1224+
}
1225+
1226+
return (buf);
1227+
}
1228+
1229+
char *
1230+
access_tpl_file(const char *tpl, int amode)
1231+
{
1232+
char *path;
1233+
const struct ebox_tpl_path_ent *tpe;
1234+
int r;
1235+
1236+
if ((amode & W_OK) == 0) {
1237+
r = access(tpl, amode);
1238+
if (r == 0)
1239+
return (strdup(tpl));
1240+
}
1241+
1242+
tpe = ebox_tpl_path;
1243+
while (tpe != NULL) {
1244+
path = compose_path(tpe->tpe_segs, tpl);
1245+
r = access(path, amode);
1246+
if (r == 0)
1247+
return (path);
1248+
free(path);
1249+
if ((amode & W_OK) == W_OK) {
1250+
path = compose_path(tpe->tpe_segs, "");
1251+
r = access(path, amode);
1252+
if (r == 0) {
1253+
free(path);
1254+
path = compose_path(tpe->tpe_segs, tpl);
1255+
return (path);
1256+
}
1257+
free(path);
1258+
}
1259+
tpe = tpe->tpe_next;
1260+
}
1261+
1262+
return (NULL);
1263+
}
1264+
1265+
FILE *
1266+
open_tpl_file(const char *tpl, const char *mode)
1267+
{
1268+
char *path;
1269+
FILE *f;
1270+
const struct ebox_tpl_path_ent *tpe;
1271+
1272+
if (strchr(mode, 'w') == NULL) {
1273+
f = fopen(tpl, mode);
1274+
if (f != NULL)
1275+
return (f);
1276+
}
1277+
1278+
tpe = ebox_tpl_path;
1279+
while (tpe != NULL) {
1280+
path = compose_path(tpe->tpe_segs, tpl);
1281+
f = fopen(path, mode);
1282+
free(path);
1283+
if (f != NULL)
1284+
return (f);
1285+
tpe = tpe->tpe_next;
1286+
}
1287+
1288+
return (NULL);
1289+
}
1290+
10611291
struct ebox_tpl *
10621292
read_tpl_file(const char *tpl)
10631293
{
@@ -1069,24 +1299,10 @@ read_tpl_file(const char *tpl)
10691299
size_t len;
10701300
int rc;
10711301
struct ebox_tpl *stpl;
1072-
char pathTpl[PATH_MAX] = { 0 };
10731302

1074-
again:
1075-
tplf = fopen(tpl, "r");
1303+
tplf = open_tpl_file(tpl, "r");
10761304
rc = errno;
1077-
if (tplf == NULL && tpl != pathTpl && errno == ENOENT) {
1078-
const char *home;
1079-
home = getenv("HOME");
1080-
if (home == NULL) {
1081-
errno = rc;
1082-
err(EXIT_ERROR, "failed to open template file '%s' "
1083-
"for reading", tpl);
1084-
}
1085-
snprintf(pathTpl, sizeof (pathTpl), TPL_DEFAULT_PATH,
1086-
home, tpl);
1087-
tpl = pathTpl;
1088-
goto again;
1089-
} else if (tplf == NULL) {
1305+
if (tplf == NULL) {
10901306
err(EXIT_ERROR, "failed to open template file '%s' for reading",
10911307
tpl);
10921308
}

ebox-cmd.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,37 @@ enum ebox_exit_status {
5858
EXIT_ALREADY_UNLOCKED = 6,
5959
};
6060

61-
#define TPL_DEFAULT_PATH "%s/.ebox/tpl/%s"
61+
enum ebox_tpl_path_seg_type {
62+
PATH_SEG_FIXED,
63+
PATH_SEG_ENV,
64+
PATH_SEG_TPL
65+
};
66+
67+
struct ebox_tpl_path_seg {
68+
struct ebox_tpl_path_seg *tps_next;
69+
enum ebox_tpl_path_seg_type tps_type;
70+
union {
71+
char *tps_fixed;
72+
char *tps_env;
73+
};
74+
};
75+
76+
struct ebox_tpl_path_ent {
77+
struct ebox_tpl_path_ent *tpe_next;
78+
char *tpe_path_tpl;
79+
struct ebox_tpl_path_seg *tpe_segs;
80+
};
81+
82+
extern struct ebox_tpl_path_ent *ebox_tpl_path;
83+
6284
#define TPL_MAX_SIZE 4096
6385
#define EBOX_MAX_SIZE 16384
6486
#define BASE64_LINE_LEN 65
6587

88+
char *compose_path(const struct ebox_tpl_path_seg *segs, const char *tpl);
89+
FILE *open_tpl_file(const char *tpl, const char *mode);
90+
char *access_tpl_file(const char *tpl, int amode);
91+
void parse_tpl_path_env(void);
6692
void release_context(void);
6793

6894
char *piv_token_shortid(struct piv_token *pk);

0 commit comments

Comments
 (0)