1/*
2 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#ifndef _H_DIRSCANNER
25#define _H_DIRSCANNER
26
27#include "resources.h"
28#include <dirent.h>
29#include <fts.h>
30#include <security_utilities/cfutilities.h>
31
32namespace Security {
33namespace CodeSigning {
34
35
36class DirScanner {
37public:
38	DirScanner(const char *path);
39	DirScanner(string path);
40	~DirScanner();
41
42	struct dirent *getNext();	// gets the next item out of this DirScanner
43	bool initialized();			// returns false if the constructor failed to initialize the dirent
44
45private:
46	string path;
47	DIR *dp = NULL;
48	void initialize();
49	bool init;
50};
51
52
53class DirValidator {
54public:
55	DirValidator() : mRequireCount(0) { }
56	~DirValidator();
57
58	enum {
59		file = 0x01,
60		directory = 0x02,
61		symlink = 0x04,
62		noexec = 0x08,
63		required = 0x10,
64		descend = 0x20,
65	};
66
67	typedef std::string (^TargetPatternBuilder)(const std::string &name, const std::string &target);
68
69private:
70	class Rule : public ResourceBuilder::Rule {
71	public:
72		Rule(const std::string &pattern, uint32_t flags, TargetPatternBuilder targetBlock);
73		~Rule();
74
75		bool matchTarget(const char *path, const char *target) const;
76
77	private:
78		TargetPatternBuilder mTargetBlock;
79	};
80	void addRule(Rule *rule) { mRules.push_back(rule); }
81
82	class FTS {
83	public:
84		FTS(const std::string &path, int options = FTS_PHYSICAL | FTS_COMFOLLOW | FTS_NOCHDIR);
85		~FTS();
86
87		operator ::FTS* () const { return mFTS; }
88
89	private:
90		::FTS *mFTS;
91	};
92
93public:
94	void allow(const std::string &namePattern, uint32_t flags, TargetPatternBuilder targetBlock = NULL)
95	{ addRule(new Rule(namePattern, flags, targetBlock)); }
96	void require(const std::string &namePattern, uint32_t flags, TargetPatternBuilder targetBlock = NULL)
97	{ addRule(new Rule(namePattern, flags | required, targetBlock)); mRequireCount++; }
98
99	void allow(const std::string &namePattern, uint32_t flags, std::string targetPattern)
100	{ allow(namePattern, flags, ^ string (const std::string &name, const std::string &target) { return targetPattern; }); }
101	void require(const std::string &namePattern, uint32_t flags, std::string targetPattern)
102	{ require(namePattern, flags, ^ string (const std::string &name, const std::string &target) { return targetPattern; }); }
103
104	void validate(const std::string &root, OSStatus error);
105
106private:
107	Rule * match(const char *relpath, uint32_t flags, bool executable, const char *target = NULL);
108
109private:
110	typedef std::vector<Rule *> Rules;
111	Rules mRules;
112	int mRequireCount;
113};
114
115
116} // end namespace CodeSigning
117} // end namespace Security
118
119#endif // !_H_DIRSCANNER
120