OpenVPN 3 Core Library
Loading...
Searching...
No Matches
dsdict.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#pragma once
13
14namespace openvpn {
15class DSDict
16{
17 public:
18 OPENVPN_EXCEPTION(dsdict_error);
19
20 DSDict(CF::DynamicStore &sc_arg, const std::string &sname_arg, const std::string &dskey_arg)
21 : sc(sc_arg),
22 sname(sname_arg),
23 dskey(dskey_arg),
24 dict(CF::DynamicStoreCopyDict(sc_arg, dskey))
25 {
26 }
27
28 bool dirty() const
29 {
30 return mod.defined() ? !CFEqual(dict(), mod()) : false;
31 }
32
34 {
35 if (dirty())
36 {
37 const CF::String keystr = CF::string(dskey);
38 if (SCDynamicStoreSetValue(sc(), keystr(), mod()))
39 {
40 OPENVPN_LOG("DSDict: updated " << dskey);
41 return true;
42 }
43 else
44 OPENVPN_LOG("DSDict: ERROR updating " << dskey);
45 }
46 return false;
47 }
48
50 {
51 if (dirty())
52 throw dsdict_error("internal error: remove_from_store called on modified dict");
53 const CF::String keystr = CF::string(dskey);
54 if (SCDynamicStoreRemoveValue(sc(), keystr()))
55 {
56 OPENVPN_LOG("DSDict: removed " << dskey);
57 return true;
58 }
59 else
60 {
61 OPENVPN_LOG("DSDict: ERROR removing " << dskey);
62 return false;
63 }
64 }
65
67 {
68 if (!mod.defined())
70 }
71
72 void mod_reset()
73 {
75 }
76
77 void backup_orig(const std::string &key, const bool wipe_orig = true)
78 {
79 const CF::String k = CF::string(key);
80 const CF::String orig = orig_key(key);
81 if (!CFDictionaryContainsKey(dict(), orig()))
82 {
83 const CF::String delval = delete_value();
84 CFTypeRef v = CFDictionaryGetValue(dict(), k());
85 if (!v)
86 v = delval();
88 CFDictionarySetValue(mod(), orig(), v);
89 }
90 if (wipe_orig)
91 {
93 CFDictionaryRemoveValue(mod(), k());
94 }
95 }
96
98 {
99 const CFIndex size = CFDictionaryGetCount(dict());
100 std::unique_ptr<const void *[]> keys(new const void *[size]);
101 std::unique_ptr<const void *[]> values(new const void *[size]);
102 CFDictionaryGetKeysAndValues(dict(), keys.get(), values.get());
103 const CF::String orig_prefix = orig_key("");
104 const CFIndex orig_prefix_len = CFStringGetLength(orig_prefix());
105 const CF::String delval = delete_value();
106 for (CFIndex i = 0; i < size; ++i)
107 {
108 const CF::String key = CF::string_cast(keys[i]);
109 if (CFStringHasPrefix(key(), orig_prefix()))
110 {
111 const CFIndex key_len = CFStringGetLength(key());
112 if (key_len > orig_prefix_len)
113 {
114 const CFRange r = CFRangeMake(orig_prefix_len, key_len - orig_prefix_len);
115 const CF::String k(CFStringCreateWithSubstring(kCFAllocatorDefault, key(), r));
116 const CFTypeRef v = values[i];
117 const CF::String vstr = CF::string_cast(v);
118 will_modify();
119 if (vstr.defined() && CFStringCompare(vstr(), delval(), 0) == kCFCompareEqualTo)
120 CFDictionaryRemoveValue(mod(), k());
121 else
122 CFDictionaryReplaceValue(mod(), k(), v);
123 CFDictionaryRemoveValue(mod(), key());
124 }
125 }
126 }
127 }
128
129 std::string to_string() const
130 {
131 std::ostringstream os;
132 os << "*** DSDict " << dskey << std::endl;
133 std::string orig = CF::description(dict());
134 string::trim_crlf(orig);
135 os << "ORIG " << orig << std::endl;
136 if (dirty())
137 {
138 std::string modstr = CF::description(mod());
139 string::trim_crlf(modstr);
140 os << "MODIFIED " << modstr << std::endl;
141 }
142 return os.str();
143 }
144
145 static CF::DynamicStore ds_create(const std::string &sname)
146 {
147 CF::String sn = CF::string(sname);
148 return CF::DynamicStore(SCDynamicStoreCreate(kCFAllocatorDefault, sn(), nullptr, nullptr));
149 }
150
151 static bool signal_network_reconfiguration(const std::string &sname)
152 {
153 const char *key = "Setup:/Network/Global/IPv4";
154 CF::DynamicStore sc = ds_create(sname);
155 const CF::String cfkey = CF::string(key);
156 OPENVPN_LOG("DSDict: SCDynamicStoreNotifyValue " << key);
157 return bool(SCDynamicStoreNotifyValue(sc(), cfkey()));
158 }
159
160 CF::DynamicStore sc;
161 const std::string sname;
162 const std::string dskey;
163 const CF::Dict dict;
164 CF::MutableDict mod;
165
166 private:
167 CF::String orig_key(const std::string &key) const
168 {
169 return CF::string(sname + "Orig" + key);
170 }
171
172 CF::String delete_value() const
173 {
174 return CF::string(sname + "DeleteValue");
175 }
176};
177} // namespace openvpn
static bool signal_network_reconfiguration(const std::string &sname)
Definition dsdict.hpp:151
bool push_to_store()
Definition dsdict.hpp:33
static CF::DynamicStore ds_create(const std::string &sname)
Definition dsdict.hpp:145
void will_modify()
Definition dsdict.hpp:66
CF::DynamicStore sc
Definition dsdict.hpp:160
std::string to_string() const
Definition dsdict.hpp:129
CF::MutableDict mod
Definition dsdict.hpp:164
const std::string sname
Definition dsdict.hpp:161
const std::string dskey
Definition dsdict.hpp:162
DSDict(CF::DynamicStore &sc_arg, const std::string &sname_arg, const std::string &dskey_arg)
Definition dsdict.hpp:20
void restore_orig()
Definition dsdict.hpp:97
bool remove_from_store()
Definition dsdict.hpp:49
CF::String orig_key(const std::string &key) const
Definition dsdict.hpp:167
bool dirty() const
Definition dsdict.hpp:28
CF::String delete_value() const
Definition dsdict.hpp:172
OPENVPN_EXCEPTION(dsdict_error)
void mod_reset()
Definition dsdict.hpp:72
void backup_orig(const std::string &key, const bool wipe_orig=true)
Definition dsdict.hpp:77
const CF::Dict dict
Definition dsdict.hpp:163
#define OPENVPN_LOG(args)
MutableDict mutable_dict_copy(const DICT &dict, const CFIndex capacity=0)
Definition cf.hpp:317
String string(const char *str)
Definition cf.hpp:221
MutableDict mutable_dict(const CFIndex capacity=0)
Definition cf.hpp:311
std::string description(CFTypeRef obj)
Definition cf.hpp:413
void trim_crlf(STRING &str)
Definition string.hpp:224
std::ostringstream os