1 /*-
2  * Copyright (c) 2011-2020 Baptiste Daroussin <bapt@FreeBSD.org>
3  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
4  * Copyright (c) 2012-2013 Bryan Drewery <bdrewery@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer
12  *    in this position and unchanged.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "pkg_config.h"
30 
31 #ifdef HAVE_CAPSICUM
32 #include <sys/capsicum.h>
33 #endif
34 
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 
39 #include <assert.h>
40 #include <ctype.h>
41 #include <errno.h>
42 #include <regex.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <stdbool.h>
46 #include <string.h>
47 #include <fcntl.h>
48 #include <unistd.h>
49 #include <uthash.h>
50 #include <err.h>
51 
52 #include "pkg.h"
53 #include "private/utils.h"
54 #include "private/event.h"
55 #include "private/pkg.h"
56 #include "private/lua.h"
57 
58 static ucl_object_t *keyword_schema = NULL;
59 
60 static int setprefix(struct plist *, char *, struct file_attr *);
61 static int dir(struct plist *, char *, struct file_attr *);
62 static int file(struct plist *, char *, struct file_attr *);
63 static int setmod(struct plist *, char *, struct file_attr *);
64 static int setowner(struct plist *, char *, struct file_attr *);
65 static int setgroup(struct plist *, char *, struct file_attr *);
66 static int comment_key(struct plist *, char *, struct file_attr *);
67 static int config(struct plist *, char *, struct file_attr *);
68 /* compat with old packages */
69 static int name_key(struct plist *, char *, struct file_attr *);
70 static int include_plist(struct plist *, char *, struct file_attr *);
71 
72 static struct action_cmd {
73 	const char *name;
74 	int (*perform)(struct plist *, char *, struct file_attr *);
75 	size_t namelen;
76 } list_actions[] = {
77 	{ "setprefix", setprefix, 9},
78 	{ "dir", dir, 3 },
79 	{ "file", file, 4 },
80 	{ "setmode", setmod, 6 },
81 	{ "setowner", setowner, 8 },
82 	{ "setgroup", setgroup, 8 },
83 	{ "comment", comment_key, 7 },
84 	{ "config", config, 6 },
85 	/* compat with old packages */
86 	{ "name", name_key, 4 },
87 	{ NULL, NULL, 0 }
88 };
89 
90 static ucl_object_t *
keyword_open_schema(void)91 keyword_open_schema(void)
92 {
93 	struct ucl_parser *parser;
94 	static const char keyword_schema_str[] = ""
95 		"{"
96 		"  type = object;"
97 		"  properties {"
98 		"    actions = { "
99 		"      type = array; "
100 		"      items = { type = string }; "
101 		"      uniqueItems: true "
102 		"    }; "
103 		"    actions_script = { type = string }; "
104 		"    arguments = { type = boolean }; "
105 		"    preformat_arguments { type = boolean }; "
106 		"    prepackaging = { type = string }; "
107 		"    deprecated = { type = boolean }; "
108 		"    deprecation_message = { type = string }; "
109 		"    attributes = { "
110 		"      type = object; "
111 		"      properties { "
112 		"        owner = { type = string }; "
113 		"        group = { type = string }; "
114 		"        mode = { oneOf: [ { type = integer }, { type = string } ] }; "
115 		"      }"
116 		"    }; "
117 		"    pre-install = { type = string }; "
118 		"    post-install = { type = string }; "
119 		"    pre-deinstall = { type = string }; "
120 		"    post-deinstall = { type = string }; "
121 		"    pre-install-lua = { type = string }; "
122 		"    post-install-lua = { type = string }; "
123 		"    pre-deinstall-lua = { type = string }; "
124 		"    post-deinstall-lua = { type = string }; "
125 		"    messages: {"
126 		"        type = array; "
127 		"        items = {"
128 		"            type = object;"
129 		"            properties {"
130 		"                message = { type = string };"
131 		"                type = { enum = [ upgrade, remove, install ] };"
132 		"            };"
133 		"            required [ message ];"
134 		"        };"
135 		"    };"
136 		"  }"
137 		"}";
138 
139 	if (keyword_schema != NULL)
140 		return (keyword_schema);
141 
142 	parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS);
143 	if (!ucl_parser_add_chunk(parser, keyword_schema_str,
144 	    sizeof(keyword_schema_str) -1)) {
145 		pkg_emit_error("Cannot parse schema for keywords: %s",
146 		    ucl_parser_get_error(parser));
147 		ucl_parser_free(parser);
148 		return (NULL);
149 	}
150 
151 	keyword_schema = ucl_parser_get_object(parser);
152 	ucl_parser_free(parser);
153 
154 	return (keyword_schema);
155 }
156 
157 void *
parse_mode(const char * str)158 parse_mode(const char *str)
159 {
160 	if (str == NULL || *str == '\0')
161 		return (NULL);
162 
163 	if (strstr(str, "u+") || strstr(str, "o+") || strstr(str, "g+") ||
164 	    strstr(str, "u-") || strstr(str, "o-") || strstr(str, "g-") ||
165 	    strstr(str, "a+") || strstr(str, "a-"))
166 		return (NULL);
167 
168 	return (setmode(str));
169 }
170 
171 void
free_file_attr(struct file_attr * a)172 free_file_attr(struct file_attr *a)
173 {
174 	if (a == NULL)
175 		return;
176 	free(a->owner);
177 	free(a->group);
178 	free(a);
179 }
180 
181 static int
setprefix(struct plist * p,char * line,struct file_attr * a __unused)182 setprefix(struct plist *p, char *line, struct file_attr *a __unused)
183 {
184 	/* if no arguments then set default prefix */
185 	if (line[0] == '\0') {
186 		strlcpy(p->prefix, p->pkg->prefix, sizeof(p->prefix));
187 	}
188 	else
189 		strlcpy(p->prefix, line, sizeof(p->prefix));
190 
191 	if (p->pkg->prefix == NULL)
192 		p->pkg->prefix = xstrdup(line);
193 
194 	p->slash = p->prefix[strlen(p->prefix) -1] == '/' ? "" : "/";
195 
196 	fprintf(p->post_install_buf->fp, "cd %s\n", p->prefix);
197 	fprintf(p->pre_deinstall_buf->fp, "cd %s\n", p->prefix);
198 	fprintf(p->post_deinstall_buf->fp, "cd %s\n", p->prefix);
199 
200 	return (EPKG_OK);
201 }
202 
203 static int
name_key(struct plist * p,char * line,struct file_attr * a __unused)204 name_key(struct plist *p, char *line, struct file_attr *a __unused)
205 {
206 	char *tmp;
207 
208 	if (p->pkg->name != NULL) {
209 		return (EPKG_OK);
210 	}
211 	tmp = strrchr(line, '-');
212 	tmp[0] = '\0';
213 	tmp++;
214 	p->pkg->name = xstrdup(line);
215 	p->pkg->version = xstrdup(tmp);
216 
217 	return (EPKG_OK);
218 }
219 
220 static int
lua_meta(lua_State * L,int (* perform)(struct plist *,char *,struct file_attr *))221 lua_meta(lua_State *L,
222     int (*perform)(struct plist *, char *, struct file_attr *))
223 {
224 	int n = lua_gettop(L);
225 	int ret;
226 	luaL_argcheck(L, n == 1, n > 1 ? 2 : n,
227 	    "takes exactly one argument");
228 	char *str = strdup(luaL_checkstring(L, 1));
229 	lua_getglobal(L, "plist");
230 	struct plist *p = lua_touserdata(L, -1);
231 	lua_getglobal(L, "attrs");
232 	struct file_attr *a = lua_touserdata(L, -1);
233 
234 	ret = perform(p, str, a);
235 	free(str);
236 	lua_pushboolean(L, ret == EPKG_OK);
237 	return (1);
238 }
239 
240 static int
lua_dir(lua_State * L)241 lua_dir(lua_State *L)
242 {
243 	return (lua_meta(L, dir));
244 }
245 
246 static int
lua_config(lua_State * L)247 lua_config(lua_State *L) {
248 	return (lua_meta(L, config));
249 }
250 
251 static int
lua_file(lua_State * L)252 lua_file(lua_State *L) {
253 	return (lua_meta(L, file));
254 }
255 
256 
257 static int
dir(struct plist * p,char * line,struct file_attr * a)258 dir(struct plist *p, char *line, struct file_attr *a)
259 {
260 	char path[MAXPATHLEN+1];
261 	char *cp;
262 	struct stat st;
263 	int ret = EPKG_OK;
264 
265 	cp = line + strlen(line) -1;
266 	while (cp > line && isspace(*cp)) {
267 		*cp = 0;
268 		cp--;
269 	}
270 
271 	if (line[0] == '/')
272 		snprintf(path, sizeof(path), "%s/", line);
273 	else
274 		snprintf(path, sizeof(path), "%s%s%s/", p->prefix, p->slash,
275 		    line);
276 
277 	if (fstatat(p->stagefd, RELATIVE_PATH(path), &st, AT_SYMLINK_NOFOLLOW)
278 	    == -1) {
279 		pkg_errno("Unable to access file %s%s",
280 		    p->stage ? p->stage: "", path);
281 		if (p->stage != NULL)
282 			ret = EPKG_FATAL;
283 		if (ctx.developer_mode) {
284 			pkg_emit_developer_mode("Plist error: @dir %s", line);
285 			ret = EPKG_FATAL;
286 		}
287 	} else {
288 		if (a != NULL)
289 			ret = pkg_adddir_attr(p->pkg, path,
290 			    a->owner ? a->owner : p->uname,
291 			    a->group ? a->group : p->gname,
292 			    a->mode ? a->mode : p->perm,
293 			    a->fflags, true);
294 		else
295 			ret = pkg_adddir_attr(p->pkg, path, p->uname, p->gname,
296 			    p->perm, 0, true);
297 	}
298 
299 	return (ret);
300 }
301 
302 static int
meta_file(struct plist * p,char * line,struct file_attr * a,bool is_config)303 meta_file(struct plist *p, char *line, struct file_attr *a, bool is_config)
304 {
305 	size_t len;
306 	char path[MAXPATHLEN];
307 	struct stat st;
308 	char *buf = NULL;
309 	bool regular = false;
310 	int ret = EPKG_OK;
311 
312 	len = strlen(line);
313 
314 	while (isspace(line[len - 1]))
315 		line[--len] = '\0';
316 
317 	if (line[0] == '/')
318 		snprintf(path, sizeof(path), "%s", line);
319 	else
320 		snprintf(path, sizeof(path), "%s%s%s", p->prefix,
321 		    p->slash, line);
322 
323 	if (fstatat(p->stagefd, RELATIVE_PATH(path), &st, AT_SYMLINK_NOFOLLOW)
324 	    == -1) {
325 		pkg_errno("Unable to access file %s%s",
326 		    p->stage ? p->stage : "", path);
327 		if (p->stage != NULL)
328 			ret = EPKG_FATAL;
329 		if (ctx.developer_mode) {
330 			pkg_emit_developer_mode("Plist error, missing file: %s",
331 			    line);
332 			ret = EPKG_FATAL;
333 		}
334 		return (ret);
335 	}
336 	buf = NULL;
337 	regular = false;
338 
339 	if (S_ISREG(st.st_mode)) {
340 		if (st.st_nlink > 1)
341 			regular = !check_for_hardlink(p->hardlinks, &st);
342 		else
343 			regular = true;
344 	} else if (S_ISLNK(st.st_mode))
345 		regular = false;
346 
347 	buf = pkg_checksum_generate_fileat(p->stagefd, RELATIVE_PATH(path),
348 	    PKG_HASH_TYPE_SHA256_HEX);
349 	if (buf == NULL) {
350 		return (EPKG_FATAL);
351 	}
352 
353 	if (regular) {
354 		p->flatsize += st.st_size;
355 		if (is_config) {
356 			off_t sz;
357 			char *content;
358 			file_to_bufferat(p->stagefd, RELATIVE_PATH(path),
359 			    &content, &sz);
360 			pkg_addconfig_file(p->pkg, path, content);
361 			free(content);
362 		}
363 	}
364 
365 	if (S_ISDIR(st.st_mode) &&
366 	    !pkg_object_bool(pkg_config_get("PLIST_ACCEPT_DIRECTORIES"))) {
367 		pkg_emit_error("Plist error, directory listed as a file: %s",
368 		    line);
369 		free(buf);
370 		return (EPKG_FATAL);
371 	}
372 
373 	if (S_ISDIR(st.st_mode)) {
374 		if (a != NULL)
375 			ret = pkg_adddir_attr(p->pkg, path,
376 			    a->owner ? a->owner : p->uname,
377 			    a->group ? a->group : p->gname,
378 			    a->mode ? a->mode : p->perm,
379 			    true, true);
380 		else
381 			ret = pkg_adddir_attr(p->pkg, path, p->uname, p->gname,
382 			    p->perm, true, true);
383 	} else {
384 		if (a != NULL)
385 			ret = pkg_addfile_attr(p->pkg, path, buf,
386 			    a->owner ? a->owner : p->uname,
387 			    a->group ? a->group : p->gname,
388 			    a->mode ? a->mode : p->perm,
389 			    a->fflags, true);
390 		else
391 			ret = pkg_addfile_attr(p->pkg, path, buf, p->uname,
392 			    p->gname, p->perm, 0, true);
393 	}
394 
395 	free(buf);
396 
397 	return (ret);
398 }
399 
400 static int
config(struct plist * p,char * line,struct file_attr * a)401 config(struct plist *p, char *line, struct file_attr *a)
402 {
403 	return (meta_file(p, line, a, true));
404 }
405 
406 static int
file(struct plist * p,char * line,struct file_attr * a)407 file(struct plist *p, char *line, struct file_attr *a)
408 {
409 	return (meta_file(p, line, a, false));
410 }
411 
412 static int
setmod(struct plist * p,char * line,struct file_attr * a __unused)413 setmod(struct plist *p, char *line, struct file_attr *a __unused)
414 {
415 	void *set;
416 
417 	p->perm = 0;
418 
419 	if (line[0] == '\0')
420 		return (EPKG_OK);
421 
422 	if ((set = parse_mode(line)) == NULL) {
423 		pkg_emit_error("%s wrong mode value", line);
424 		return (EPKG_FATAL);
425 	}
426 	p->perm = getmode(set, 0);
427 	return (EPKG_OK);
428 }
429 
430 static int
setowner(struct plist * p,char * line,struct file_attr * a __unused)431 setowner(struct plist *p, char *line, struct file_attr *a __unused)
432 {
433 	free(p->uname);
434 	if (line[0] == '\0')
435 		p->uname = xstrdup("root");
436 	else
437 		p->uname = xstrdup(line);
438 	return (EPKG_OK);
439 }
440 
441 static int
setgroup(struct plist * p,char * line,struct file_attr * a __unused)442 setgroup(struct plist *p, char *line, struct file_attr *a __unused)
443 {
444 	free(p->gname);
445 	if (line[0] == '\0')
446 		p->gname = xstrdup("wheel");
447 	else
448 		p->gname = xstrdup(line);
449 	return (EPKG_OK);
450 }
451 
452 static int
comment_key(struct plist * p __unused,char * line __unused,struct file_attr * a __unused)453 comment_key(struct plist *p __unused, char *line __unused , struct file_attr *a __unused)
454 {
455 	/* ignore md5 will be recomputed anyway */
456 	return (EPKG_OK);
457 }
458 
459 static struct keyact {
460 	const char *key;
461 	int (*action)(struct plist *, char *, struct file_attr *);
462 } keyacts[] = {
463 	{ "cwd", setprefix },
464 	{ "comment", comment_key },
465 	{ "config", config },
466 	{ "dir", dir },
467 	{ "include", include_plist },
468 	{ "mode", setmod },
469 	{ "owner", setowner },
470 	{ "group", setgroup },
471 	/* old pkg compat */
472 	{ "name", name_key },
473 	{ NULL, NULL },
474 };
475 
476 static struct lua_map {
477 	const char *key;
478 	pkg_lua_script type;
479 } lua_mapping[] = {
480 	{ "pre-install-lua", PKG_LUA_PRE_INSTALL },
481 	{ "post-install-lua", PKG_LUA_POST_INSTALL },
482 	{ "pre-deinstall-lua", PKG_LUA_PRE_DEINSTALL },
483 	{ "post-deinstall-lua", PKG_LUA_POST_DEINSTALL },
484 };
485 
486 static struct script_map {
487 	const char *key;
488 	pkg_script type;
489 } script_mapping[] = {
490 	{ "pre-install", PKG_SCRIPT_PRE_INSTALL },
491 	{ "post-install", PKG_SCRIPT_POST_INSTALL },
492 	{ "pre-deinstall", PKG_SCRIPT_PRE_DEINSTALL },
493 	{ "post-deinstall", PKG_SCRIPT_POST_DEINSTALL },
494 };
495 
496 static void
populate_keywords(struct plist * p)497 populate_keywords(struct plist *p)
498 {
499 	struct keyword *k;
500 	struct action *a;
501 	int i;
502 
503 	for (i = 0; keyacts[i].key != NULL; i++) {
504 		k = xcalloc(1, sizeof(struct keyword));
505 		a = xmalloc(sizeof(struct action));
506 		strlcpy(k->keyword, keyacts[i].key, sizeof(k->keyword));
507 		a->perform = keyacts[i].action;
508 		DL_APPEND(k->actions, a);
509 		HASH_ADD_STR(p->keywords, keyword, k);
510 	}
511 }
512 
513 static void
keyword_free(struct keyword * k)514 keyword_free(struct keyword *k)
515 {
516 	DL_FREE(k->actions, free);
517 	free(k);
518 }
519 
520 static int
parse_actions(const ucl_object_t * o,struct plist * p,char * line,struct file_attr * a,int argc,char ** argv)521 parse_actions(const ucl_object_t *o, struct plist *p,
522     char *line, struct file_attr *a, int argc, char **argv)
523 {
524 	const ucl_object_t *cur;
525 	const char *actname;
526 	ucl_object_iter_t it = NULL;
527 	int i, j = 0;
528 	int r, rc = EPKG_OK;
529 
530 	while ((cur = ucl_iterate_object(o, &it, true))) {
531 		actname = ucl_object_tostring(cur);
532 		for (i = 0; list_actions[i].name != NULL; i++) {
533 			if (!strncasecmp(actname, list_actions[i].name,
534 			    list_actions[i].namelen) &&
535 			    (actname[list_actions[i].namelen ] == '\0' ||
536 			     actname[list_actions[i].namelen ] == '(' )) {
537 				actname += list_actions[i].namelen;
538 				if (*actname == '(') {
539 					if (strspn(actname + 1, "1234567890")
540 					    != strlen(actname + 1) - 1) {
541 						pkg_emit_error(
542 						    "Invalid argument: "
543 						    "expecting a number "
544 						    "got %s", actname);
545 						return (EPKG_FATAL);
546 					}
547 					j = strtol(actname+1, NULL, 10);
548 					if (j > argc) {
549 						pkg_emit_error(
550 						    "Invalid argument requested %d"
551 						    " available: %d", j, argc);
552 						return (EPKG_FATAL);
553 					}
554 				}
555 				r = list_actions[i].perform(p, j > 0 ? argv[j - 1] : line, a);
556 				if (r != EPKG_OK && rc == EPKG_OK)
557 					rc = r;
558 				break;
559 			}
560 		}
561 	}
562 
563 	return (rc);
564 }
565 
566 static void
parse_attributes(const ucl_object_t * o,struct file_attr ** a)567 parse_attributes(const ucl_object_t *o, struct file_attr **a)
568 {
569 	const ucl_object_t *cur;
570 	ucl_object_iter_t it = NULL;
571 	const char *key;
572 
573 	if (*a == NULL)
574 		*a = xcalloc(1, sizeof(struct file_attr));
575 
576 	while ((cur = ucl_iterate_object(o, &it, true))) {
577 		key = ucl_object_key(cur);
578 		if (key == NULL)
579 			continue;
580 		if (!strcasecmp(key, "owner") && cur->type == UCL_STRING) {
581 			free((*a)->owner);
582 			(*a)->owner = xstrdup(ucl_object_tostring(cur));
583 			continue;
584 		}
585 		if (!strcasecmp(key, "group") && cur->type == UCL_STRING) {
586 			free((*a)->group);
587 			(*a)->group = xstrdup(ucl_object_tostring(cur));
588 			continue;
589 		}
590 		if (!strcasecmp(key, "mode")) {
591 			if (cur->type == UCL_STRING) {
592 				void *set;
593 				if ((set = parse_mode(ucl_object_tostring(cur))) == NULL) {
594 					pkg_emit_error("Bad format for the mode attribute: %s", ucl_object_tostring(cur));
595 					return;
596 				}
597 				(*a)->mode = getmode(set, 0);
598 				free(set);
599 			} else {
600 				pkg_emit_error("Expecting a string for the mode attribute, ignored");
601 			}
602 		}
603 	}
604 }
605 
606 static void
append_script(struct plist * p,pkg_script t,const char * cmd)607 append_script(struct plist *p, pkg_script t, const char *cmd)
608 {
609 	switch (t) {
610 	case PKG_SCRIPT_PRE_INSTALL:
611 		fprintf(p->pre_install_buf->fp, "%s\n", cmd);
612 		break;
613 	case PKG_SCRIPT_POST_INSTALL:
614 		fprintf(p->post_install_buf->fp, "%s\n", cmd);
615 		break;
616 	case PKG_SCRIPT_PRE_DEINSTALL:
617 		fprintf(p->pre_deinstall_buf->fp, "%s\n", cmd);
618 		break;
619 	case PKG_SCRIPT_POST_DEINSTALL:
620 		fprintf(p->post_deinstall_buf->fp, "%s\n", cmd);
621 		break;
622 	}
623 }
624 
625 static int
apply_keyword_file(ucl_object_t * obj,struct plist * p,char * line,struct file_attr * attr)626 apply_keyword_file(ucl_object_t *obj, struct plist *p, char *line, struct file_attr *attr)
627 {
628 	const ucl_object_t *o, *cur, *elt;
629 	ucl_object_iter_t it = NULL;
630 	struct pkg_message *msg;
631 	char *cmd;
632 	const char *l = line;
633 	char *formated_line = NULL;
634 	char **args = NULL;
635 	char *buf, *tofree = NULL;
636 	struct file_attr *freeattr = NULL;
637 	int spaces, argc = 0;
638 	int ret = EPKG_FATAL;
639 
640 	if ((o = ucl_object_find_key(obj,  "arguments")) && ucl_object_toboolean(o)) {
641 		spaces = pkg_utils_count_spaces(line);
642 		args = xmalloc((spaces + 1)* sizeof(char *));
643 		tofree = buf = xstrdup(line);
644 		while (buf != NULL) {
645 			args[argc++] = pkg_utils_tokenize(&buf);
646 		}
647 	}
648 
649 	if ((o = ucl_object_find_key(obj,  "attributes")))
650 		parse_attributes(o, attr != NULL ? &attr : &freeattr);
651 
652 	if ((o = ucl_object_find_key(obj,  "preformat_arguments")) &&
653 	    ucl_object_toboolean(o)) {
654 		format_exec_cmd(&formated_line, line, p->prefix, p->last_file, NULL, 0,
655 				NULL, false);
656 		l = formated_line;
657 	}
658 	/* add all shell scripts */
659 	for (int i = 0; i < nitems(script_mapping); i++) {
660 		if ((o = ucl_object_find_key(obj, script_mapping[i].key))) {
661 			if (format_exec_cmd(&cmd, ucl_object_tostring(o), p->prefix,
662 			    p->last_file, l, argc, args, false) != EPKG_OK)
663 				goto keywords_cleanup;
664 			append_script(p, script_mapping[i].type, cmd);
665 			free(cmd);
666 		}
667 	}
668 
669 	/* add all lua scripts */
670 	for (int i = 0; i < nitems(lua_mapping); i++) {
671 		if ((o = ucl_object_find_key(obj, lua_mapping[i].key))) {
672 			if (format_exec_cmd(&cmd, ucl_object_tostring(o), p->prefix,
673 			    p->last_file, l, argc, args, true) != EPKG_OK)
674 				goto keywords_cleanup;
675 			pkg_add_lua_script(p->pkg, cmd, lua_mapping[i].type);
676 			free(cmd);
677 		}
678 	}
679 	free(formated_line);
680 
681 	if ((o = ucl_object_find_key(obj, "messages"))) {
682 		while ((cur = ucl_iterate_object(o, &it, true))) {
683 			elt = ucl_object_find_key(cur, "message");
684 			msg = xcalloc(1, sizeof(*msg));
685 			msg->str = xstrdup(ucl_object_tostring(elt));
686 			msg->type = PKG_MESSAGE_ALWAYS;
687 			elt = ucl_object_find_key(cur, "type");
688 			if (elt != NULL) {
689 				if (strcasecmp(ucl_object_tostring(elt), "install") == 0)
690 					msg->type = PKG_MESSAGE_INSTALL;
691 				else if (strcasecmp(ucl_object_tostring(elt), "remove") == 0)
692 					msg->type = PKG_MESSAGE_REMOVE;
693 				else if (strcasecmp(ucl_object_tostring(elt), "upgrade") == 0)
694 					msg->type = PKG_MESSAGE_UPGRADE;
695 			}
696 			DL_APPEND(p->pkg->message, msg);
697 		}
698 	}
699 
700 	ret = EPKG_OK;
701 	if ((o = ucl_object_find_key(obj,  "actions")))
702 		ret = parse_actions(o, p, line, attr, argc, args);
703 
704 	if (ret == EPKG_OK && (o = ucl_object_find_key(obj, "prepackaging"))) {
705 		lua_State *L = luaL_newstate();
706 		static const luaL_Reg plist_lib[] = {
707 			{ "config", lua_config },
708 			{ "dir", lua_dir },
709 			{ "file", lua_file },
710 			{ NULL, NULL },
711 		};
712 		luaL_openlibs(L);
713 		lua_pushlightuserdata(L, p);
714 		lua_setglobal(L, "plist");
715 		lua_pushlightuserdata(L, attr);
716 		lua_setglobal(L, "attrs");
717 		lua_pushstring(L, line);
718 		lua_setglobal(L, "line");
719 		lua_args_table(L, args, argc);
720 		luaL_newlib(L, plist_lib);
721 		lua_setglobal(L, "pkg");
722 		lua_override_ios(L, false);
723 		pkg_debug(3, "Scripts: executing lua\n--- BEGIN ---"
724 		    "\n%s\nScripts: --- END ---", ucl_object_tostring(o));
725 		if (luaL_dostring(L, ucl_object_tostring(o))) {
726 			pkg_emit_error("Failed to execute lua script: "
727 			    "%s", lua_tostring(L, -1));
728 			ret = EPKG_FATAL;
729 		}
730 		if (lua_tonumber(L, -1) != 0) {
731 			ret = EPKG_FATAL;
732 		}
733 		lua_close(L);
734 	}
735 
736 keywords_cleanup:
737 	free(args);
738 	free(tofree);
739 	return (ret);
740 }
741 
742 static int
external_keyword(struct plist * plist,char * keyword,char * line,struct file_attr * attr)743 external_keyword(struct plist *plist, char *keyword, char *line, struct file_attr *attr)
744 {
745 	struct ucl_parser *parser;
746 	const char *keyword_dir = NULL;
747 	char keyfile_path[MAXPATHLEN];
748 	int ret = EPKG_UNKNOWN, fd;
749 	ucl_object_t *o, *schema;
750 	const ucl_object_t *obj;
751 	struct ucl_schema_error err;
752 
753 	keyword_dir = pkg_object_string(pkg_config_get("PLIST_KEYWORDS_DIR"));
754 	if (keyword_dir == NULL) {
755 		keyword_dir = pkg_object_string(pkg_config_get("PORTSDIR"));
756 		snprintf(keyfile_path, sizeof(keyfile_path),
757 		    "%s/Keywords/%s.ucl", keyword_dir, keyword);
758 	} else {
759 		snprintf(keyfile_path, sizeof(keyfile_path),
760 		    "%s/%s.ucl", keyword_dir, keyword);
761 	}
762 
763 	fd = open(keyfile_path, O_RDONLY);
764 	if (fd == -1) {
765 		pkg_emit_error("cannot load keyword from %s: %s",
766 				keyfile_path, strerror(errno));
767 		return (EPKG_UNKNOWN);
768 	}
769 
770 	parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS);
771 	if (!ucl_parser_add_fd(parser, fd)) {
772 		pkg_emit_error("cannot parse keyword: %s",
773 				ucl_parser_get_error(parser));
774 		ucl_parser_free(parser);
775 		close(fd);
776 		return (EPKG_UNKNOWN);
777 	}
778 
779 	close(fd);
780 	o = ucl_parser_get_object(parser);
781 	ucl_parser_free(parser);
782 
783 	schema = keyword_open_schema();
784 
785 	if (schema != NULL) {
786 		if (!ucl_object_validate(schema, o, &err)) {
787 			pkg_emit_error("Keyword definition %s cannot be validated: %s", keyfile_path, err.msg);
788 			ucl_object_unref(o);
789 			return (EPKG_FATAL);
790 		}
791 	}
792 
793 	if ((obj = ucl_object_find_key(o, "deprecated")) &&
794 	    ucl_object_toboolean(obj)) {
795 		obj = ucl_object_find_key(o, "deprecation_message");
796 		pkg_emit_error("Use of '@%s' is deprecated%s%s", keyword,
797 		   obj != NULL ? ": " : "",
798 		   obj != NULL ? ucl_object_tostring(obj) : "");
799 		if (ctx.developer_mode) {
800 			ucl_object_unref(o);
801 			return (EPKG_FATAL);
802 		}
803 	}
804 	ret = apply_keyword_file(o, plist, line, attr);
805 	if (ret != EPKG_OK) {
806 		pkg_emit_error("Fail to apply keyword '%s'", keyword);
807 	}
808 
809 	return (ret);
810 }
811 
812  struct file_attr *
parse_keyword_args(char * args,char * keyword)813 parse_keyword_args(char *args, char *keyword)
814 {
815 	struct file_attr *attr;
816 	char *owner, *group, *permstr, *fflags;
817 	void *set = NULL;
818 	u_long fset = 0;
819 
820 	owner = group = permstr = fflags = NULL;
821 
822 	/* remove last ')' */
823 	args[strlen(args) -1] = '\0';
824 
825 	do {
826 		args[0] = '\0';
827 		args++;
828 		while (isspace(*args))
829 			args++;
830 		if (*args == '\0')
831 			break;
832 		if (owner == NULL) {
833 			owner = args;
834 		} else if (group == NULL) {
835 			group = args;
836 		} else if (permstr == NULL) {
837 			permstr = args;
838 		} else if (fflags == NULL) {
839 			fflags = args;
840 			break;
841 		} else {
842 			return (NULL);
843 		}
844 	} while ((args = strchr(args, ',')) != NULL);
845 
846 	if (fflags != NULL && *fflags != '\0') {
847 #ifdef HAVE_STRTOFFLAGS
848 		if (strtofflags(&fflags, &fset, NULL) != 0) {
849 			pkg_emit_error("Malformed keyword '%s', wrong fflags",
850 			    keyword);
851 			return (NULL);
852 		}
853 #else
854 		pkg_emit_error("Malformed keyword '%s', maximum 3 arguments "
855 		    "are accepted", keyword);
856 #endif
857 	}
858 
859 	if (permstr != NULL && *permstr != '\0') {
860 		if ((set = parse_mode(permstr)) == NULL) {
861 			pkg_emit_error("Malformed keyword '%s', wrong mode "
862 			    "section", keyword);
863 			return (NULL);
864 		}
865 	}
866 	if (owner == NULL && group == NULL && set == NULL)
867 		return (NULL);
868 
869 	attr = xcalloc(1, sizeof(struct file_attr));
870 	if (owner != NULL && *owner != '\0')
871 		attr->owner = xstrdup(rtrimspace(owner));
872 	if (group != NULL && *group != '\0')
873 		attr->group = xstrdup(rtrimspace(group));
874 	if (set != NULL) {
875 		attr->mode = getmode(set, 0);
876 		free(set);
877 	}
878 	attr->fflags = fset;
879 
880 	return (attr);
881 }
882 
883 static int
parse_keywords(struct plist * plist,char * keyword,char * line,struct file_attr * attr)884 parse_keywords(struct plist *plist, char *keyword,
885     char *line, struct file_attr *attr)
886 {
887 	struct keyword *k;
888 	struct action *a;
889 	int ret = EPKG_FATAL;
890 
891 	/* if keyword is empty consider it as a file */
892 	if (*keyword == '\0')
893 		return (file(plist, line, attr));
894 
895 	HASH_FIND_STR(plist->keywords, keyword, k);
896 	if (k != NULL) {
897 		LL_FOREACH(k->actions, a) {
898 			ret = a->perform(plist, line, attr);
899 			if (ret != EPKG_OK)
900 				break;
901 		}
902 		return (ret);
903 	}
904 
905 	/*
906 	 * if we are here it means the keyword has not been found
907 	 * maybe it is defined externally
908 	 * let's try to find it
909 	 */
910 	return (external_keyword(plist, keyword, line, attr));
911 }
912 
913 char *
extract_keywords(char * line,char ** keyword,struct file_attr ** attr)914 extract_keywords(char *line, char **keyword, struct file_attr **attr)
915 {
916 	char *k, *buf, *tmp;
917 	struct file_attr *a = NULL;
918 
919 	buf = k = line;
920 	while (!(isspace(buf[0]) || buf[0] == '\0')) {
921 		if (buf[0] == '(' && (buf = strchr(buf, ')')) == NULL)
922 			return (NULL);
923 		buf++;
924 	}
925 	if (buf[0] != '\0') {
926 		buf[0] = '\0';
927 		buf++;
928 	}
929 
930 	/* trim spaces after the keyword */
931 	while (isspace(buf[0]))
932 		buf++;
933 
934 	pkg_debug(1, "Parsing plist, found keyword: '%s", k);
935 
936 	if ((tmp = strchr(k, '(')) != NULL && k[strlen(k) -1] != ')')
937 		return (NULL);
938 
939 	if (tmp != NULL) {
940 		a = parse_keyword_args(tmp, k);
941 		if (a == NULL)
942 			return (NULL);
943 	}
944 
945 	*attr = a;
946 	*keyword = k;
947 
948 	return (buf);
949 }
950 
951 static void
flush_script_buffer(xstring * buf,struct pkg * p,int type)952 flush_script_buffer(xstring *buf, struct pkg *p, int type)
953 {
954 	fflush(buf->fp);
955 	if (buf->buf[0] != '\0') {
956 		pkg_appendscript(p, buf->buf, type);
957 	}
958 }
959 
960 int
plist_parse_line(struct plist * plist,char * line)961 plist_parse_line(struct plist *plist, char *line)
962 {
963 	char *keyword, *buf, *bkpline;
964 	struct file_attr *a;
965 
966 	if (line[0] == '\0')
967 		return (EPKG_OK);
968 
969 	pkg_debug(1, "Parsing plist line: '%s'", line);
970 	bkpline = xstrdup(line);
971 
972 	if (line[0] == '@') {
973 		keyword = NULL;
974 		a = NULL;
975 		buf = extract_keywords(line + 1, &keyword, &a);
976 		if (buf == NULL) {
977 			pkg_emit_error("Malformed keyword %s, expecting @keyword "
978 			    "or @keyword(owner,group,mode)", bkpline);
979 			free(bkpline);
980 			return (EPKG_FATAL);
981 		}
982 
983 		switch (parse_keywords(plist, keyword, buf, a)) {
984 		case EPKG_UNKNOWN:
985 			pkg_emit_error("unknown keyword %s: %s",
986 			    keyword, line);
987 			/* FALLTHRU */
988 		case EPKG_FATAL:
989 			free(bkpline);
990 			return (EPKG_FATAL);
991 		}
992 	} else {
993 		buf = line;
994 		strlcpy(plist->last_file, buf, sizeof(plist->last_file));
995 
996 		/* remove spaces at the begining and at the end */
997 		while (isspace(buf[0]))
998 			buf++;
999 
1000 		if (file(plist, buf, NULL) != EPKG_OK) {
1001 			free(bkpline);
1002 			return (EPKG_FATAL);
1003 		}
1004 	}
1005 
1006 	free(bkpline);
1007 	return (EPKG_OK);
1008 }
1009 
1010 struct plist *
plist_new(struct pkg * pkg,const char * stage)1011 plist_new(struct pkg *pkg, const char *stage)
1012 {
1013 	struct plist *p;
1014 
1015 	p = xcalloc(1, sizeof(struct plist));
1016 	if (p == NULL)
1017 		return (NULL);
1018 
1019 	p->plistdirfd = -1;
1020 	p->stagefd = open(stage ? stage : "/", O_DIRECTORY | O_CLOEXEC);
1021 	if (p->stagefd == -1) {
1022 		free(p);
1023 		return (NULL);
1024 	}
1025 
1026 	p->pkg = pkg;
1027 	if (pkg->prefix != NULL)
1028 		strlcpy(p->prefix, pkg->prefix, sizeof(p->prefix));
1029 	p->slash = *p->prefix != '\0' && p->prefix[strlen(p->prefix) - 1] == '/' ? "" : "/";
1030 	p->stage = stage;
1031 
1032 	p->uname = xstrdup("root");
1033 	p->gname = xstrdup("wheel");
1034 
1035 	p->pre_install_buf = xstring_new();
1036 	p->post_install_buf = xstring_new();
1037 	p->pre_deinstall_buf = xstring_new();
1038 	p->post_deinstall_buf = xstring_new();
1039 	p->hardlinks = kh_init_hardlinks();
1040 
1041 	populate_keywords(p);
1042 
1043 	return (p);
1044 }
1045 
1046 void
plist_free(struct plist * p)1047 plist_free(struct plist *p)
1048 {
1049 	if (p == NULL)
1050 		return;
1051 
1052 	if (p->stagefd != -1)
1053 		close(p->stagefd);
1054 	if (p->plistdirfd != -1)
1055 		close(p->plistdirfd);
1056 
1057 	HASH_FREE(p->keywords, keyword_free);
1058 
1059 	free(p->uname);
1060 	free(p->gname);
1061 	free(p->post_patterns.buf);
1062 	free(p->post_patterns.patterns);
1063 	kh_destroy_hardlinks(p->hardlinks);
1064 
1065 	xstring_free(p->post_deinstall_buf);
1066 	xstring_free(p->post_install_buf);
1067 	xstring_free(p->pre_deinstall_buf);
1068 	xstring_free(p->pre_install_buf);
1069 
1070 	free(p);
1071 }
1072 
1073 static int
plist_parse(struct plist * pplist,FILE * f)1074 plist_parse(struct plist *pplist, FILE *f)
1075 {
1076 	int ret, rc = EPKG_OK;
1077 	size_t linecap = 0;
1078 	ssize_t linelen;
1079 	char *line = NULL;
1080 
1081 	while ((linelen = getline(&line, &linecap, f)) > 0) {
1082 		if (line[linelen - 1] == '\n')
1083 			line[linelen - 1] = '\0';
1084 		ret = plist_parse_line(pplist, line);
1085 		if (ret != EPKG_OK && rc == EPKG_OK)
1086 			rc = ret;
1087 	}
1088 	free(line);
1089 
1090 	return (rc);
1091 }
1092 
1093 static int
open_directory_of(const char * file)1094 open_directory_of(const char *file)
1095 {
1096 	char path[MAXPATHLEN];
1097 	char *walk;
1098 
1099 	if (strchr(file, '/') == NULL) {
1100 		if (getcwd(path, MAXPATHLEN) == NULL) {
1101 			pkg_emit_error("Unable to determine current location");
1102 			return (-1);
1103 		}
1104 		return (open(path, O_DIRECTORY));
1105 	}
1106 	strlcpy(path, file, sizeof(path));
1107 	walk = strrchr(path, '/');
1108 	*walk = '\0';
1109 	return (open(path, O_DIRECTORY));
1110 }
1111 
1112 int
include_plist(struct plist * p,char * name,struct file_attr * a __unused)1113 include_plist(struct plist *p, char *name, struct file_attr *a __unused)
1114 {
1115 	FILE *f;
1116 	int fd;
1117 	int rc;
1118 
1119 	if (p->in_include) {
1120 		pkg_emit_error("Inside in @include it is not allowed to reuse @include");
1121 		return (EPKG_FATAL);
1122 	}
1123 	p->in_include = true;
1124 
1125 	fd = openat(p->plistdirfd, name, O_RDONLY);
1126 	if (fd == -1) {
1127 		pkg_emit_errno("Inpossible to include", name);
1128 		return (EPKG_FATAL);
1129 	}
1130 	f = fdopen(fd, "r");
1131 	if (f == NULL) {
1132 		pkg_emit_errno("Inpossible to include", name);
1133 		close(fd);
1134 		return (EPKG_FATAL);
1135 	}
1136 
1137 	rc = plist_parse(p, f);
1138 
1139 	fclose(f);
1140 	return (rc);
1141 }
1142 
1143 int
ports_parse_plist(struct pkg * pkg,const char * plist,const char * stage)1144 ports_parse_plist(struct pkg *pkg, const char *plist, const char *stage)
1145 {
1146 	int rc = EPKG_OK;
1147 	struct plist *pplist;
1148 	FILE *plist_f;
1149 
1150 	assert(pkg != NULL);
1151 	assert(plist != NULL);
1152 
1153 	if ((pplist = plist_new(pkg, stage)) == NULL)
1154 		return (EPKG_FATAL);
1155 
1156 	pplist->plistdirfd = open_directory_of(plist);
1157 	if (pplist->plistdirfd == -1) {
1158 		pkg_emit_error("impossible to open the directory where the plist is: %s", plist);
1159 		plist_free(pplist);
1160 		return (EPKG_FATAL);
1161 	}
1162 	if ((plist_f = fopen(plist, "re")) == NULL) {
1163 		pkg_emit_error("Unable to open plist file: %s", plist);
1164 		plist_free(pplist);
1165 		return (EPKG_FATAL);
1166 	}
1167 
1168 	rc = plist_parse(pplist, plist_f);
1169 
1170 	pkg->flatsize = pplist->flatsize;
1171 
1172 	flush_script_buffer(pplist->pre_install_buf, pkg,
1173 	    PKG_SCRIPT_PRE_INSTALL);
1174 	flush_script_buffer(pplist->post_install_buf, pkg,
1175 	    PKG_SCRIPT_POST_INSTALL);
1176 	flush_script_buffer(pplist->pre_deinstall_buf, pkg,
1177 	    PKG_SCRIPT_PRE_DEINSTALL);
1178 	flush_script_buffer(pplist->post_deinstall_buf, pkg,
1179 	    PKG_SCRIPT_POST_DEINSTALL);
1180 
1181 	fclose(plist_f);
1182 
1183 	plist_free(pplist);
1184 
1185 	return (rc);
1186 }
1187 
1188 /*
1189  * if the provided database is NULL then we don't want to register the package
1190  * in the database aka NO_PKG_REGISTER
1191  */
1192 int
pkg_add_port(struct pkgdb * db,struct pkg * pkg,const char * input_path,const char * reloc,bool testing)1193 pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *input_path,
1194     const char *reloc, bool testing)
1195 {
1196 	const char *location;
1197 	int rc = EPKG_OK;
1198 	xstring *message;
1199 	struct pkg_message *msg;
1200 
1201 	if (db != NULL && pkg_is_installed(db, pkg->name) != EPKG_END) {
1202 		return(EPKG_INSTALLED);
1203 	}
1204 
1205 	location = reloc;
1206 	if (ctx.pkg_rootdir != NULL)
1207 		location = ctx.pkg_rootdir;
1208 
1209 	if (ctx.pkg_rootdir == NULL && location != NULL)
1210 		pkg_kv_add(&pkg->annotations, "relocated", location, "annotation");
1211 
1212 	pkg_emit_install_begin(pkg);
1213 
1214 	if (db != NULL) {
1215 		rc = pkgdb_register_pkg(db, pkg, 0, NULL);
1216 
1217 		if (rc != EPKG_OK)
1218 			goto cleanup;
1219 	}
1220 
1221 	if (!testing) {
1222 		/* Execute pre-install scripts */
1223 		pkg_lua_script_run(pkg, PKG_LUA_PRE_INSTALL, false);
1224 		pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL, false);
1225 
1226 		if (input_path != NULL) {
1227 			pkg_register_cleanup_callback(pkg_rollback_cb, pkg);
1228 			rc = pkg_add_fromdir(pkg, input_path);
1229 			pkg_unregister_cleanup_callback(pkg_rollback_cb, pkg);
1230 			if (rc != EPKG_OK) {
1231 				pkg_rollback_pkg(pkg);
1232 				if (db != NULL)
1233 					pkg_delete_dirs(db, pkg, NULL);
1234 			}
1235 		}
1236 
1237 		/* Execute post-install scripts */
1238 		pkg_lua_script_run(pkg, PKG_LUA_POST_INSTALL, false);
1239 		pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL, false);
1240 	}
1241 
1242 	if (rc == EPKG_OK) {
1243 		pkg_emit_install_finished(pkg, NULL);
1244 		if (pkg->message != NULL)
1245 			message = xstring_new();
1246 		LL_FOREACH(pkg->message, msg) {
1247 			if (msg->type == PKG_MESSAGE_ALWAYS ||
1248 			    msg->type == PKG_MESSAGE_INSTALL) {
1249 				fprintf(message->fp, "%s\n", msg->str);
1250 			}
1251 		}
1252 		if (pkg->message != NULL) {
1253 			fflush(message->fp);
1254 			if (message->buf[0] != '\0') {
1255 				pkg_emit_message(message->buf);
1256 			}
1257 			xstring_free(message);
1258 		}
1259 	}
1260 	/* it is impossible at this point to get any cleanup triggers to run */
1261 	triggers_execute(NULL);
1262 
1263 cleanup:
1264 	if (db != NULL)
1265 		pkgdb_register_finale(db, rc, NULL);
1266 
1267 	return (rc);
1268 }
1269