]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/CertificateData.cc
f84296624b49fa9f7eceedc985e6f9af903550ab
[thirdparty/squid.git] / src / acl / CertificateData.cc
1 /*
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 28 Access Control */
10
11 #include "squid.h"
12 #include "acl/CertificateData.h"
13 #include "acl/Checklist.h"
14 #include "cache_cf.h"
15 #include "ConfigParser.h"
16 #include "Debug.h"
17 #include "wordlist.h"
18
19 ACLCertificateData::ACLCertificateData(Ssl::GETX509ATTRIBUTE *sslStrategy, const char *attrs, bool optionalAttr) : validAttributesStr(attrs), attributeIsOptional(optionalAttr), attribute (NULL), values (), sslAttributeCall (sslStrategy)
20 {
21 if (attrs) {
22 size_t current = 0;
23 size_t next = std::string::npos;
24 std::string valid(attrs);
25 do {
26 next = valid.find_first_of( "|", current);
27 validAttributes.push_back(valid.substr( current, (next == std::string::npos ? std::string::npos : next - current)));
28 current = next + 1;
29 } while (next != std::string::npos);
30 }
31 }
32
33 ACLCertificateData::ACLCertificateData(ACLCertificateData const &old) : attribute (NULL), values (old.values), sslAttributeCall (old.sslAttributeCall)
34 {
35 validAttributesStr = old.validAttributesStr;
36 validAttributes.assign (old.validAttributes.begin(), old.validAttributes.end());
37 attributeIsOptional = old.attributeIsOptional;
38 if (old.attribute)
39 attribute = xstrdup(old.attribute);
40 }
41
42 template<class T>
43 inline void
44 xRefFree(T &thing)
45 {
46 xfree (thing);
47 }
48
49 ACLCertificateData::~ACLCertificateData()
50 {
51 safe_free (attribute);
52 }
53
54 template<class T>
55 inline int
56 splaystrcmp (T&l, T&r)
57 {
58 return strcmp ((char *)l,(char *)r);
59 }
60
61 bool
62 ACLCertificateData::match(X509 *cert)
63 {
64 if (!cert)
65 return 0;
66
67 char const *value = sslAttributeCall(cert, attribute);
68 debugs(28, 6, (attribute ? attribute : "value") << "=" << value);
69 if (value == NULL)
70 return 0;
71
72 return values.match(value);
73 }
74
75 SBufList
76 ACLCertificateData::dump() const
77 {
78 SBufList sl;
79 if (validAttributesStr)
80 sl.push_back(SBuf(attribute));
81
82 #if __cplusplus >= 201103L
83 sl.splice(sl.end(),values.dump());
84 #else
85 // temp is needed until c++11 move constructor
86 SBufList tmp = values.dump();
87 sl.splice(sl.end(),tmp);
88 #endif
89 return sl;
90 }
91
92 void
93 ACLCertificateData::parse()
94 {
95 if (validAttributesStr) {
96 char *newAttribute = ConfigParser::strtokFile();
97
98 if (!newAttribute) {
99 if (attributeIsOptional)
100 return;
101
102 debugs(28, DBG_CRITICAL, "FATAL: required attribute argument missing");
103 self_destruct();
104 }
105
106 // Handle the cases where we have optional -x type attributes
107 if (attributeIsOptional && newAttribute[0] != '-')
108 // The read token is not an attribute/option, so add it to values list
109 values.insert(newAttribute);
110 else {
111 bool valid = false;
112 for (std::list<std::string>::const_iterator it = validAttributes.begin(); it != validAttributes.end(); ++it) {
113 if (*it == "*" || *it == newAttribute) {
114 valid = true;
115 break;
116 }
117 }
118
119 if (!valid) {
120 debugs(28, DBG_CRITICAL, "FATAL: Unknown option. Supported option(s) are: " << validAttributesStr);
121 self_destruct();
122 }
123
124 /* an acl must use consistent attributes in all config lines */
125 if (attribute) {
126 if (strcasecmp(newAttribute, attribute) != 0) {
127 debugs(28, DBG_CRITICAL, "FATAL: An acl must use consistent attributes in all config lines (" << newAttribute << "!=" << attribute << ").");
128 self_destruct();
129 }
130 } else {
131 if (strcasecmp(newAttribute, "DN") != 0) {
132 int nid = OBJ_txt2nid(newAttribute);
133 if (nid == 0) {
134 const size_t span = strspn(newAttribute, "0123456789.");
135 if(newAttribute[span] == '\0') { // looks like a numerical OID
136 // create a new object based on this attribute
137
138 // NOTE: Not a [bad] leak: If the same attribute
139 // has been added before, the OBJ_txt2nid call
140 // would return a valid nid value.
141 // TODO: call OBJ_cleanup() on reconfigure?
142 nid = OBJ_create(newAttribute, newAttribute, newAttribute);
143 debugs(28, 7, "New SSL certificate attribute created with name: " << newAttribute << " and nid: " << nid);
144 }
145 }
146 if (nid == 0) {
147 debugs(28, DBG_CRITICAL, "FATAL: Not valid SSL certificate attribute name or numerical OID: " << newAttribute);
148 self_destruct();
149 }
150 }
151 attribute = xstrdup(newAttribute);
152 }
153 }
154 }
155
156 values.parse();
157 }
158
159 bool
160 ACLCertificateData::empty() const
161 {
162 return values.empty();
163 }
164
165 ACLData<X509 *> *
166 ACLCertificateData::clone() const
167 {
168 /* Splay trees don't clone yet. */
169 return new ACLCertificateData(*this);
170 }
171